vfs: mmap support

. libc: add vfs_mmap, a way for vfs to initiate mmap()s.
	  This is a good special case to have as vfs is a slightly
	  different client from regular user processes. It doesn't do it
	  for itself, and has the dev & inode info already so the callback
	  to VFS for the lookup isn't necessary. So it has different info
	  to have to give to VM.
	. libc: also add minix_mmap64() that accepts a 64-bit offset, even
	  though our off_t is still 32 bit now.
	. to support mmap, we need to create new references to FD's (such
	  as an FD) so that the mmapped object can never be removed even if
	  all FD's are closed. To do that we conceptually dup the
	  filedescriptor into a new range that is only visible to the system.
	  So there are FDS_PER_PROCESS fd's, which is more than OPEN_MAX,
	  per process, and user processes can still use up to OPEN_MAX
	  FD's. mmap()ped objects then get extra reference in the invisible
	  range so user processes can't close them. The in-vfs fd_set is
	  of size FDS_PER_PROCESS.
	. On exec() time, try to mmap() in the executable if available.
	  (It is not yet available in this commit.)
	. To support mmap(), add do_vm_call that allows VM to lookup
	  (to ino+dev), do i/o from and close FD's on behalf of other
	  processes.
	. To make this possible, a few functions have 2 more arguments
	  to make the target process explicit (instead of the implicit
	  global fp) and to specify whether the request is from a user
	  process or the system (which implies whether FD's starting at
	  OPEN_MAX are valid). These are close_fd, common_open, actual_llseek,
	  actual_read_write_peek, get_fd and get_filp2.

Change-Id: I831551e45a6781c74313c450eb9c967a68505932
This commit is contained in:
Ben Gras 2013-05-07 12:41:07 +00:00
parent fd5f2edf35
commit db40bc9db0
33 changed files with 453 additions and 125 deletions

View File

@ -734,6 +734,7 @@ struct
{ "PROCCTL", VM_PROCCTL },
{ "MAPCACHEPAGE", VM_MAPCACHEPAGE },
{ "SETCACHEPAGE", VM_SETCACHEPAGE },
{ "VFS_MMAP", VM_VFS_MMAP },
{ NULL, 0 },
};

View File

@ -94,7 +94,8 @@ service vfs
VIRCOPY # 15
MEMSET
;
vm PROCCTL;
vm PROCCTL
VFS_MMAP;
io NONE; # No I/O range allowed
irq NONE; # No IRQ allowed
sigmgr rs; # Signal manager is RS

View File

@ -1,4 +1,4 @@
#define NCALLS 117 /* number of system calls allowed */
#define NCALLS 118 /* number of system calls allowed */
/* In case it isn't obvious enough: this list is sorted numerically. */
#define EXIT 1
@ -107,6 +107,8 @@
#define CLOCK_GETTIME 115 /* clock_gettime() */
#define CLOCK_SETTIME 116 /* clock_settime() */
#define VFS_VMCALL 117
#define TASK_REPLY 121 /* to VFS: reply code from drivers, not
* really a standalone call.
*/

View File

@ -1005,6 +1005,7 @@
# define VMV_DEV m10_i4
# define VMV_INO m10_l1
# define VMV_FD m10_l2
# define VMV_SIZE_PAGES m10_l3
#define VM_REMAP (VM_RQ_BASE+33)
# define VMRE_D m1_i1
@ -1075,8 +1076,10 @@
#define VMPPARAM_CLEAR 1 /* values for VMPCTL_PARAM */
#define VM_VFS_MMAP (VM_RQ_BASE+46)
/* Total. */
#define NR_VM_CALLS 46
#define NR_VM_CALLS 47
#define VM_CALL_MASK_SIZE BITMAP_CHUNKS(NR_VM_CALLS)
/* not handled as a normal VM call, thus at the end of the reserved rage */
@ -1086,8 +1089,8 @@
/* Basic vm calls allowed to every process. */
#define VM_BASIC_CALLS \
VM_MMAP, VM_MUNMAP, VM_MAP_PHYS, VM_UNMAP_PHYS, \
VM_INFO, VM_MAPCACHEPAGE
VM_MMAP, VM_VFS_REPLY, VM_MUNMAP, VM_MAP_PHYS, VM_UNMAP_PHYS, \
VM_INFO
/*===========================================================================*
* Messages for IPC server *

View File

@ -26,6 +26,14 @@ int vm_forgetblock(u64_t id);
void vm_forgetblocks(void);
int vm_yield_block_get_block(u64_t yieldid, u64_t getid, void *mem,
vir_bytes len);
int minix_vfs_mmap(endpoint_t who, u32_t offset, u32_t len,
u32_t dev, u32_t ino, u16_t fd, u32_t vaddr, u16_t clearend, u16_t
flags);
/* minix vfs mmap flags */
#define MVM_LENMASK 0x0FFF
#define MVM_FLAGSMASK 0xF000
#define MVM_WRITABLE 0x8000
/* Invalid ID with special meaning for the vm_yield_block_get_block
* interface.

View File

@ -51,12 +51,38 @@ void *minix_mmap_for(endpoint_t forwhom,
return (void *) m.VMM_RETADDR;
}
int minix_vfs_mmap(endpoint_t who, u32_t offset, u32_t len,
u32_t dev, u32_t ino, u16_t fd, u32_t vaddr, u16_t clearend,
u16_t flags)
{
message m;
memset(&m, 0, sizeof(message));
m.m_u.m_vm_vfs.who = who;
m.m_u.m_vm_vfs.offset = offset;
m.m_u.m_vm_vfs.dev = dev;
m.m_u.m_vm_vfs.ino = ino;
m.m_u.m_vm_vfs.vaddr = vaddr;
m.m_u.m_vm_vfs.len = len;
m.m_u.m_vm_vfs.fd = fd;
m.m_u.m_vm_vfs.clearend_and_flags = clearend | flags;
return _syscall(VM_PROC_NR, VM_VFS_MMAP, &m);
}
void *minix_mmap(void *addr, size_t len, int prot, int flags,
int fd, off_t offset)
{
return minix_mmap_for(SELF, addr, len, prot, flags, fd, offset);
}
void *minix_mmap64(void *addr, size_t len, int prot, int flags,
int fd, u64_t offset)
{
return minix_mmap_for(SELF, addr, len, prot, flags, fd, offset);
}
int minix_munmap(void *addr, size_t len)
{
message m;

View File

@ -249,7 +249,11 @@ int libexec_load_elf(struct exec_info *execi)
#endif
}
} else {
if(try_mmap) printf("libexec: mmap failed\n");
static int printed = 0;
if(try_mmap && !printed) {
printf("libexec: mmap failing\n");
printed = 1;
}
/* make us some memory */
if(execi->allocmem_prealloc_junk(execi, vaddr, seg_membytes) != OK) {

View File

@ -6,6 +6,8 @@
#define _SYSTEM 1 /* get OK and negative error codes */
#include "../vfs/fdset.h"
#include <sys/types.h>
#include <limits.h>
#include <errno.h>

View File

@ -1,7 +1,7 @@
#ifndef __PFS_CONST_H__
#define __PFS_CONST_H__
#define NR_INODES 256 /* # slots in "in core" inode table */
#define PFS_NR_INODES 512 /* # slots in "in core" inode table */
/* Size of descriptor table for unix domain sockets. This should be
* equal to the maximum number of minor devices (currently 256).

View File

@ -24,6 +24,6 @@ EXTERN int busy;
EXTERN int unmountdone;
/* Inode map. */
EXTERN bitchunk_t inodemap[FS_BITMAP_CHUNKS(NR_INODES)];
EXTERN bitchunk_t inodemap[FS_BITMAP_CHUNKS(PFS_NR_INODES)];
#endif

View File

@ -81,7 +81,7 @@ void init_inode_cache()
LIST_INIT(rlp);
/* add free inodes to unused/free list */
for (rip = &inode[0]; rip < &inode[NR_INODES]; ++rip) {
for (rip = &inode[0]; rip < &inode[PFS_NR_INODES]; ++rip) {
rip->i_num = NO_ENTRY;
TAILQ_INSERT_HEAD(&unused_inodes, rip, i_unused);
}
@ -309,7 +309,7 @@ struct inode *rip;
bit_t b;
if (rip->i_num <= (ino_t) 0 || rip->i_num >= (ino_t) NR_INODES) return;
if (rip->i_num <= (ino_t) 0 || rip->i_num >= (ino_t) PFS_NR_INODES) return;
b = (bit_t) rip->i_num;
free_bit(b);
}

View File

@ -27,7 +27,7 @@ EXTERN struct inode {
TAILQ_ENTRY(inode) i_unused; /* free and unused list */
} inode[NR_INODES];
} inode[PFS_NR_INODES];
/* list of unused/free inodes */
EXTERN TAILQ_HEAD(unused_inodes_t, inode) unused_inodes;

View File

@ -128,7 +128,7 @@ static int sef_cb_init_fresh(int type, sef_init_info_t *info)
busy = 0; /* Server is not 'busy' (i.e., inodes in use). */
/* Init inode table */
for (i = 0; i < NR_INODES; ++i) {
for (i = 0; i < PFS_NR_INODES; ++i) {
inode[i].i_count = 0;
}

View File

@ -24,7 +24,7 @@ bit_t alloc_bit(void)
bit_t b;
unsigned int i, bcount;
bcount = FS_BITMAP_CHUNKS(NR_INODES); /* Inode map has this many chunks. */
bcount = FS_BITMAP_CHUNKS(PFS_NR_INODES); /* Inode map has this many chunks. */
wlim = &inodemap[bcount]; /* Point to last chunk in inodemap. */
for (wptr = &inodemap[0]; wptr < wlim; wptr++) {
@ -38,7 +38,7 @@ bit_t alloc_bit(void)
b = (bit_t) ((wptr - &inodemap[0]) * FS_BITCHUNK_BITS + i);
/* Don't allocate bits beyond end of map. */
if (b >= NR_INODES) break;
if (b >= PFS_NR_INODES) break;
/* Allocate and return bit number. */
*wptr |= 1 << i;

View File

@ -128,6 +128,7 @@ int (*call_vec[])(void) = {
do_getres, /* 114 = clock_getres */
do_gettime, /* 115 = clock_gettime */
do_settime, /* 116 = clock_settime */
no_sys, /* 117 = (vmcall) */
};
/* This should not fail with "array size is negative": */
extern int dummy[sizeof(call_vec) == NCALLS * sizeof(call_vec[0]) ? 1 : -1];

View File

@ -3,6 +3,8 @@
#define _SYSTEM 1
#include "vfs/fdset.h"
#include <minix/config.h>
#include <limits.h>
#include <errno.h>

View File

@ -1,11 +1,18 @@
#ifndef __VFS_CONST_H__
#define __VFS_CONST_H__
/* How many FD's must be reserved per process? OPEN_MAX are
* user-visible, SYSTEM_FDS_MAX are system-usable.
*/
#define SYSTEM_FDSTART OPEN_MAX /* How many user FD's */
#define SYSTEM_FDS_MAX OPEN_MAX /* How many system FD's */
#define FDS_PER_PROCESS (OPEN_MAX+SYSTEM_FDS_MAX) /* Total FD's */
/* Tables sizes */
#define NR_FILPS 512 /* # slots in filp table */
#define NR_FILPS 1024 /* # slots in filp table */
#define NR_LOCKS 8 /* # slots in the file locking table */
#define NR_MNTS 16 /* # slots in mount table */
#define NR_VNODES 512 /* # slots in vnode table */
#define NR_VNODES 1024 /* # slots in vnode table */
#define NR_WTHREADS 8 /* # slots in worker thread table */
#define NR_NONEDEVS NR_MNTS /* # slots in nonedev bitmap */

View File

@ -177,7 +177,7 @@ static void adjust_offsets(Elf_Phdr phdrs[], int phnum)
*===========================================================================*/
static void write_buf(struct filp *f, char *buf, size_t size)
{
read_write(WRITING, f, buf, size, VFS_PROC_NR);
read_write(fp, WRITING, f, buf, size, VFS_PROC_NR);
}
/*===========================================================================*

View File

@ -16,6 +16,7 @@
#include "fs.h"
#include <sys/stat.h>
#include <sys/mman.h>
#include <minix/callnr.h>
#include <minix/endpoint.h>
#include <minix/com.h>
@ -30,6 +31,7 @@
#include "path.h"
#include "param.h"
#include "vnode.h"
#include "file.h"
#include <minix/vfsif.h>
#include <machine/vmparam.h>
#include <assert.h>
@ -48,6 +50,8 @@ struct vfs_exec_info {
int is_dyn; /* Dynamically linked executable */
int elf_main_fd; /* Dyn: FD of main program execuatble */
char execname[PATH_MAX]; /* Full executable invocation */
int procfd;
int procfd_used;
};
static void lock_exec(void);
@ -185,6 +189,27 @@ static int get_read_vp(struct vfs_exec_info *execi,
r=get_read_vp(&e,f,p,s,rs,fp); if(r != OK) { FAILCHECK(r); } \
} while(0)
static int vfs_memmap(struct exec_info *execi,
vir_bytes vaddr, vir_bytes len, vir_bytes foffset, u16_t clearend,
int protflags)
{
struct vfs_exec_info *vi = (struct vfs_exec_info *) execi->opaque;
struct vnode *vp = ((struct vfs_exec_info *) execi->opaque)->vp;
int r;
u16_t flags = 0;
if(protflags & PROT_WRITE)
flags |= MVM_WRITABLE;
r = minix_vfs_mmap(execi->proc_e, foffset, len,
vp->v_dev, vp->v_inode_nr, vi->procfd, vaddr, clearend, flags);
if(r == OK) {
vi->procfd_used = 1;
}
return r;
}
/*===========================================================================*
* pm_exec *
*===========================================================================*/
@ -205,14 +230,18 @@ int pm_exec(endpoint_t proc_e, vir_bytes path, size_t path_len,
int i;
static char fullpath[PATH_MAX],
elf_interpreter[PATH_MAX],
firstexec[PATH_MAX],
finalexec[PATH_MAX];
struct lookup resolve;
stackhook_t makestack = NULL;
static int n;
n++;
lock_exec();
/* unset execi values are 0. */
memset(&execi, 0, sizeof(execi));
execi.procfd = -1;
/* passed from exec() libc code */
execi.userflags = user_exec_flags;
@ -223,6 +252,7 @@ int pm_exec(endpoint_t proc_e, vir_bytes path, size_t path_len,
rfp = fp = &fproc[slot];
lookup_init(&resolve, fullpath, PATH_NOFLAGS, &execi.vmp, &execi.vp);
resolve.l_vmnt_lock = VMNT_READ;
resolve.l_vnode_lock = VNODE_READ;
@ -244,6 +274,7 @@ int pm_exec(endpoint_t proc_e, vir_bytes path, size_t path_len,
/* Get the exec file name. */
FAILCHECK(fetch_name(path, path_len, fullpath));
strlcpy(finalexec, fullpath, PATH_MAX);
strlcpy(firstexec, fullpath, PATH_MAX);
/* Get_read_vp will return an opened vn in execi.
* if necessary it releases the existing vp so we can
@ -264,6 +295,7 @@ int pm_exec(endpoint_t proc_e, vir_bytes path, size_t path_len,
FAILCHECK(fetch_name(path, path_len, fullpath));
FAILCHECK(patch_stack(execi.vp, mbuf, &frame_len, fullpath));
strlcpy(finalexec, fullpath, PATH_MAX);
strlcpy(firstexec, fullpath, PATH_MAX);
Get_read_vp(execi, fullpath, 1, 0, &resolve, fp);
}
@ -280,7 +312,7 @@ int pm_exec(endpoint_t proc_e, vir_bytes path, size_t path_len,
/* The interpreter (loader) needs an fd to the main program,
* which is currently in finalexec
*/
if((r = execi.elf_main_fd = common_open(finalexec, O_RDONLY, 0)) < 0) {
if((r = execi.elf_main_fd = common_open(finalexec, O_RDONLY, 0, 1)) < 0) {
printf("VFS: exec: dynamic: open main exec failed %s (%d)\n",
fullpath, r);
FAILCHECK(r);
@ -299,9 +331,25 @@ int pm_exec(endpoint_t proc_e, vir_bytes path, size_t path_len,
* be looked up
*/
strlcpy(fullpath, elf_interpreter, PATH_MAX);
strlcpy(firstexec, elf_interpreter, PATH_MAX);
Get_read_vp(execi, fullpath, 0, 0, &resolve, fp);
}
/* We also want an FD so VM can mmap() the process in if possible. */
{
int openr;
if((openr=execi.procfd=common_open(firstexec, O_RDONLY, 0, 0)) < 0) {
printf("vfs: exec: open failed of %s (%d), can't mmap\n",
firstexec, openr);
execi.procfd = -1;
} else {
if(fp->fp_filp[openr]->filp_vno->v_vmnt->m_haspeek &&
major(fp->fp_filp[openr]->filp_vno->v_dev) != MEMORY_MAJOR) {
execi.args.memmap = vfs_memmap;
}
}
}
/* callback functions and data */
execi.args.copymem = read_seg;
execi.args.clearproc = libexec_clearproc_vm_procctl;
@ -358,7 +406,13 @@ pm_execfinal:
unlock_vnode(execi.vp);
put_vnode(execi.vp);
}
if(execi.procfd >= 0 && !execi.procfd_used) {
int r;
r = close_fd(rfp, execi.procfd, 0);
}
unlock_exec();
return(r);
}
@ -649,9 +703,9 @@ static void clo_exec(struct fproc *rfp)
int i;
/* Check the file desriptors one by one for presence of FD_CLOEXEC. */
for (i = 0; i < OPEN_MAX; i++)
for (i = 0; i < FDS_PER_PROCESS; i++)
if ( FD_ISSET(i, &rfp->fp_cloexec_set))
(void) close_fd(rfp, i);
(void) close_fd(rfp, i, 0);
}
/*===========================================================================*

11
servers/vfs/fdset.h Normal file
View File

@ -0,0 +1,11 @@
#ifndef _FDSET_H
#define _FDSET_H 1
#include "const.h"
#ifdef FD_SETSIZE
#error FD_SETSIZE already set
#endif
#define FD_SETSIZE FDS_PER_PROCESS
#include <sys/fd_set.h>
#endif

View File

@ -15,12 +15,13 @@
* the receiver.
*/
#include "fs.h"
#include <sys/select.h>
#include <minix/callnr.h>
#include <minix/u64.h>
#include <assert.h>
#include <sys/stat.h>
#include "fs.h"
#include "file.h"
#include "fproc.h"
#include "vnode.h"
@ -147,7 +148,8 @@ void init_filps(void)
/*===========================================================================*
* get_fd *
*===========================================================================*/
int get_fd(int start, mode_t bits, int *k, struct filp **fpt)
int get_fd(struct fproc *rfp, int start, mode_t bits, int *k,
struct filp **fpt, int userfd)
{
/* Look for a free file descriptor and a free filp slot. Fill in the mode word
* in the latter, but don't claim either one yet, since the open() or creat()
@ -156,10 +158,11 @@ int get_fd(int start, mode_t bits, int *k, struct filp **fpt)
register struct filp *f;
register int i;
int limit = userfd ? OPEN_MAX : FDS_PER_PROCESS;
/* Search the fproc fp_filp table for a free file descriptor. */
for (i = start; i < OPEN_MAX; i++) {
if (fp->fp_filp[i] == NULL && !FD_ISSET(i, &fp->fp_filp_inuse)) {
for (i = start; i < limit; i++) {
if (rfp->fp_filp[i] == NULL && !FD_ISSET(i, &rfp->fp_filp_inuse)) {
/* A file descriptor has been located. */
*k = i;
break;
@ -167,7 +170,7 @@ int get_fd(int start, mode_t bits, int *k, struct filp **fpt)
}
/* Check to see if a file descriptor has been found. */
if (i >= OPEN_MAX) return(EMFILE);
if (i >= limit) return(EMFILE);
/* If we don't care about a filp, return now */
if (fpt == NULL) return(OK);
@ -203,32 +206,35 @@ int fild; /* file descriptor */
tll_access_t locktype;
{
/* See if 'fild' refers to a valid file descr. If so, return its filp ptr. */
return get_filp2(fp, fild, locktype);
return get_filp2(fp, fild, locktype, 1);
}
/*===========================================================================*
* get_filp2 *
*===========================================================================*/
struct filp *get_filp2(rfp, fild, locktype)
struct filp *get_filp2(rfp, fild, locktype, userrequest)
register struct fproc *rfp;
int fild; /* file descriptor */
tll_access_t locktype;
int userrequest;
{
/* See if 'fild' refers to a valid file descr. If so, return its filp ptr. */
struct filp *filp;
int fdlimit = userrequest ? OPEN_MAX : FDS_PER_PROCESS;
filp = NULL;
if (fild < 0 || fild >= OPEN_MAX)
if (fild < 0 || fild >= fdlimit) {
err_code = EBADF;
else if (rfp->fp_filp[fild] == NULL && FD_ISSET(fild, &rfp->fp_filp_inuse))
} else if (rfp->fp_filp[fild] == NULL && FD_ISSET(fild, &rfp->fp_filp_inuse))
err_code = EIO; /* The filedes is not there, but is not closed either.
*/
else if ((filp = rfp->fp_filp[fild]) == NULL)
else if ((filp = rfp->fp_filp[fild]) == NULL) {
err_code = EBADF;
else
} else {
assert(filp->filp_count > 0);
lock_filp(filp, locktype); /* All is fine */
}
return(filp); /* may also be NULL */
}
@ -269,7 +275,7 @@ int invalidate_filp(struct filp *rfilp)
int f, fd, n = 0;
for (f = 0; f < NR_PROCS; f++) {
if (fproc[f].fp_pid == PID_FREE) continue;
for (fd = 0; fd < OPEN_MAX; fd++) {
for (fd = 0; fd < FDS_PER_PROCESS; fd++) {
if(fproc[f].fp_filp[fd] && fproc[f].fp_filp[fd] == rfilp) {
fproc[f].fp_filp[fd] = NULL;
n++;
@ -435,7 +441,7 @@ int fd;
if (isokendpt(ep, &slot) != OK)
return(NULL);
rfilp = get_filp2(&fproc[slot], fd, VNODE_READ);
rfilp = get_filp2(&fproc[slot], fd, VNODE_READ, 1);
return(rfilp);
}
@ -498,7 +504,7 @@ filp_id_t cfilp;
rfp = &fproc[slot];
/* Find an open slot in fp_filp */
for (fd = 0; fd < OPEN_MAX; fd++) {
for (fd = 0; fd < FDS_PER_PROCESS; fd++) {
if (rfp->fp_filp[fd] == NULL &&
!FD_ISSET(fd, &rfp->fp_filp_inuse)) {

View File

@ -2,6 +2,7 @@
#define __VFS_FPROC_H__
#include "threads.h"
#include "fdset.h"
#include <sys/select.h>
#include <minix/safecopies.h>
@ -20,7 +21,7 @@ EXTERN struct fproc {
struct vnode *fp_wd; /* working directory; NULL during reboot */
struct vnode *fp_rd; /* root directory; NULL during reboot */
struct filp *fp_filp[OPEN_MAX];/* the file descriptor table */
struct filp *fp_filp[FDS_PER_PROCESS]; /* the file descriptor table */
fd_set fp_filp_inuse; /* which fd's are in use? */
fd_set fp_cloexec_set; /* bit map for POSIX Table 6-2 FD_CLOEXEC */

View File

@ -6,8 +6,12 @@
*/
#define _SYSTEM 1 /* tell headers that this is the kernel */
/* Get the right-sized fd_set */
#include "fdset.h"
/* The following are so basic, all the *.c files get them automatically. */
#include <minix/config.h> /* MUST be first */
#include <minix/config.h>
#include <sys/types.h>
#include <minix/const.h>
#include <minix/type.h>
@ -23,7 +27,6 @@
#include <minix/sysutil.h>
#include <minix/timers.h>
#include "const.h"
#include "dmap.h"
#include "proto.h"
#include "threads.h"

View File

@ -758,8 +758,9 @@ static void get_work()
}
proc_p = _ENDPOINT_P(m_in.m_source);
if (proc_p < 0 || proc_p >= NR_PROCS) fp = NULL;
else fp = &fproc[proc_p];
if (proc_p < 0 || proc_p >= NR_PROCS) {
fp = NULL;
} else fp = &fproc[proc_p];
if (m_in.m_type == EDEADSRCDST) return; /* Failed 'sendrec' */

View File

@ -131,7 +131,7 @@ int do_fcntl(message *UNUSED(m_out))
case F_DUPFD:
/* This replaces the old dup() system call. */
if (fcntl_argx < 0 || fcntl_argx >= OPEN_MAX) r = EINVAL;
else if ((r = get_fd(fcntl_argx, 0, &new_fd, NULL)) == OK) {
else if ((r = get_fd(fp, fcntl_argx, 0, &new_fd, NULL, 1)) == OK) {
f->filp_count++;
fp->fp_filp[new_fd] = f;
FD_SET(new_fd, &fp->fp_filp_inuse);
@ -311,6 +311,144 @@ int do_fsync(message *UNUSED(m_out))
return(r);
}
/*===========================================================================*
* do_vm_call *
*===========================================================================*/
int do_vm_call(message *m_out)
{
/* A call that VM does to VFS.
* We must reply with the fixed type VM_VFS_REPLY (and put our result info
* in the rest of the message) so VM can tell the difference between a
* request from VFS and a reply to this call.
*/
int req = job_m_in.VFS_VMCALL_REQ;
int req_fd = job_m_in.VFS_VMCALL_FD;
u32_t req_id = job_m_in.VFS_VMCALL_REQID;
endpoint_t ep = job_m_in.VFS_VMCALL_ENDPOINT;
u64_t offset = make64(job_m_in.VFS_VMCALL_OFFSET_LO,
job_m_in.VFS_VMCALL_OFFSET_HI);
u32_t length = job_m_in.VFS_VMCALL_LENGTH;
int result = OK;
int slot;
struct fproc *rfp, *vmf;
struct filp *f = NULL;
if(job_m_in.m_source != VM_PROC_NR)
return ENOSYS;
okendpt(ep, &slot);
rfp = &fproc[slot];
vmf = &fproc[VM_PROC_NR];
assert(fp == vmf);
assert(rfp != vmf);
lock_proc(rfp, 1);
switch(req) {
case VMVFSREQ_FDLOOKUP:
{
int procfd;
/* Lookup fd in referenced process. */
if ((f = get_filp2(rfp, req_fd, VNODE_READ, 1)) == NULL) {
result = err_code;
goto reqdone;
}
assert(f->filp_vno);
assert(f->filp_vno->v_vmnt);
if(!f->filp_vno->v_vmnt->m_haspeek) {
result = EINVAL;
goto reqdone;
}
if (!S_ISREG(f->filp_vno->v_mode) &&
!S_ISBLK(f->filp_vno->v_mode)) {
printf("VFS: mmap regular/blockdev only; dev 0x%x ino %d has mode 0%o\n",
f->filp_vno->v_dev, f->filp_vno->v_inode_nr, f->filp_vno->v_mode);
result = EINVAL;
goto reqdone;
}
if((result=get_fd(rfp, SYSTEM_FDSTART, 0, &procfd,
NULL, 0)) != OK)
goto reqdone;
if(S_ISBLK(f->filp_vno->v_mode)) {
assert(f->filp_vno->v_sdev != NO_DEV);
m_out->VMV_DEV = f->filp_vno->v_sdev;
m_out->VMV_INO = VMC_NO_INODE;
m_out->VMV_SIZE_PAGES = LONG_MAX;
} else {
m_out->VMV_DEV = f->filp_vno->v_dev;
m_out->VMV_INO = f->filp_vno->v_inode_nr;
m_out->VMV_SIZE_PAGES =
roundup(f->filp_vno->v_size,
PAGE_SIZE)/PAGE_SIZE;
}
m_out->VMV_FD = procfd;
f->filp_count++;
assert(f->filp_count > 0);
rfp->fp_filp[procfd] = f;
/* mmap FD's are inuse and close-on-exec */
FD_SET(procfd, &rfp->fp_filp_inuse);
FD_SET(procfd, &rfp->fp_cloexec_set);
result = OK;
break;
}
case VMVFSREQ_FDCLOSE:
{
result = close_fd(rfp, req_fd, 0);
if(result != OK) {
printf("VFS: VM fd close for fd %d, %d (%d)\n",
req_fd, rfp->fp_endpoint, result);
}
break;
}
case VMVFSREQ_FDIO:
{
message dummy_out;
result = actual_llseek(rfp, &dummy_out, req_fd,
SEEK_SET, offset, 0);
if(result != OK) {
printf("VFS: llseek for mmap i/o for %d, fd %d, (offset %llu) failed (%d)\n",
rfp->fp_endpoint, req_fd, offset, result);
} else {
result = actual_read_write_peek(rfp, PEEKING,
req_fd, NULL, length, 0);
}
break;
}
default:
panic("VFS: bad request code from VM\n");
break;
}
reqdone:
if(f)
unlock_filp(f);
unlock_proc(rfp);
/* fp is VM still. */
assert(fp == vmf);
m_out->VMV_ENDPOINT = ep;
m_out->VMV_RESULT = result;
m_out->VMV_REQID = req_id;
return VM_VFS_REPLY;
}
/*===========================================================================*
* pm_reboot *
*===========================================================================*/
@ -397,7 +535,7 @@ void pm_fork(endpoint_t pproc, endpoint_t cproc, pid_t cpid)
cp = &fproc[childno];
pp = &fproc[parentno];
for (i = 0; i < OPEN_MAX; i++)
for (i = 0; i < FDS_PER_PROCESS; i++)
if (cp->fp_filp[i] != NULL) cp->fp_filp[i]->filp_count++;
/* Fill in new process and endpoint id. */
@ -441,8 +579,8 @@ static void free_proc(struct fproc *exiter, int flags)
unpause(exiter->fp_endpoint);
/* Loop on file descriptors, closing any that are open. */
for (i = 0; i < OPEN_MAX; i++) {
(void) close_fd(exiter, i);
for (i = 0; i < FDS_PER_PROCESS; i++) {
(void) close_fd(exiter, i, 0);
}
/* Release root and working directories. */
@ -478,7 +616,7 @@ static void free_proc(struct fproc *exiter, int flags)
if(rfp->fp_pid == PID_FREE) continue;
if (rfp->fp_tty == dev) rfp->fp_tty = 0;
for (i = 0; i < OPEN_MAX; i++) {
for (i = 0; i < FDS_PER_PROCESS; i++) {
if ((rfilp = rfp->fp_filp[i]) == NULL) continue;
if (rfilp->filp_mode == FILP_CLOSED) continue;
vp = rfilp->filp_vno;
@ -685,6 +823,8 @@ int pm_dumpcore(endpoint_t proc_e, int csig, vir_bytes exe_name)
struct filp *f;
char core_path[PATH_MAX];
char proc_name[PROC_NAME_LEN];
static int seq = 0;
seq++;
okendpt(proc_e, &slot);
fp = &fproc[slot];
@ -696,8 +836,8 @@ int pm_dumpcore(endpoint_t proc_e, int csig, vir_bytes exe_name)
unpause(fp->fp_endpoint);
/* open core file */
snprintf(core_path, PATH_MAX, "%s.%d", CORE_NAME, fp->fp_pid);
core_fd = common_open(core_path, O_WRONLY | O_CREAT | O_TRUNC, CORE_MODE);
snprintf(core_path, PATH_MAX, "%s.%d.%d", CORE_NAME, fp->fp_pid, seq);
core_fd = common_open(core_path, O_WRONLY | O_CREAT | O_TRUNC, CORE_MODE, 1);
if (core_fd < 0) { r = core_fd; goto core_exit; }
/* get process' name */
@ -709,7 +849,7 @@ int pm_dumpcore(endpoint_t proc_e, int csig, vir_bytes exe_name)
if ((f = get_filp(core_fd, VNODE_WRITE)) == NULL) { r=EBADF; goto core_exit; }
write_elf_core_file(f, csig, proc_name);
unlock_filp(f);
(void) close_fd(fp, core_fd); /* ignore failure, we're exiting anyway */
(void) close_fd(fp, core_fd, 0); /* ignore failure, we're exiting anyway */
core_exit:
if(csig)
@ -768,3 +908,4 @@ void panic_hook(void)
printf("VFS mthread stacktraces:\n");
mthread_stacktraces();
}

View File

@ -72,14 +72,14 @@ int do_open(message *UNUSED(m_out))
}
if (r != OK) return(err_code); /* name was bad */
return common_open(fullpath, open_mode, create_mode);
return common_open(fullpath, open_mode, create_mode, 1);
}
/*===========================================================================*
* common_open *
*===========================================================================*/
int common_open(char path[PATH_MAX], int oflags, mode_t omode)
int common_open(char path[PATH_MAX], int oflags, mode_t omode, int userfd)
{
/* Common code from do_creat and do_open. */
int b, r, exist = TRUE, major_dev;
@ -90,13 +90,16 @@ int common_open(char path[PATH_MAX], int oflags, mode_t omode)
struct vmnt *vmp;
struct dmap *dp;
struct lookup resolve;
int start = userfd ? 0 : SYSTEM_FDSTART;
/* Remap the bottom two bits of oflags. */
bits = (mode_t) mode_map[oflags & O_ACCMODE];
if (!bits) return(EINVAL);
/* See if file descriptor and filp slots are available. */
if ((r = get_fd(0, bits, &(scratch(fp).file.fd_nr), &filp)) != OK) return(r);
if ((r = get_fd(fp, start, bits, &(scratch(fp).file.fd_nr),
&filp, userfd)) != OK)
return(r);
lookup_init(&resolve, path, PATH_NOFLAGS, &vmp, &vp);
@ -587,21 +590,13 @@ int do_mkdir(message *UNUSED(m_out))
return(r);
}
/*===========================================================================*
* do_lseek *
*===========================================================================*/
int do_lseek(message *m_out)
int actual_lseek(message *m_out, int seekfd, int seekwhence, off_t offset)
{
/* Perform the lseek(ls_fd, offset, whence) system call. */
register struct filp *rfilp;
int r = OK, seekfd, seekwhence;
off_t offset;
int r = OK;
u64_t pos, newpos;
seekfd = job_m_in.ls_fd;
seekwhence = job_m_in.whence;
offset = (off_t) job_m_in.offset_lo;
/* Check to see if the file descriptor is valid. */
if ( (rfilp = get_filp(seekfd, VNODE_READ)) == NULL) return(err_code);
@ -647,23 +642,32 @@ int do_lseek(message *m_out)
}
/*===========================================================================*
* do_llseek *
* do_lseek *
*===========================================================================*/
int do_llseek(message *m_out)
int do_lseek(message *m_out)
{
return actual_lseek(m_out, job_m_in.ls_fd, job_m_in.whence,
(off_t) job_m_in.offset_lo);
}
/*===========================================================================*
* actual_llseek *
*===========================================================================*/
int actual_llseek(struct fproc *rfp, message *m_out, int seekfd, int seekwhence,
u64_t offset, int userreq)
{
/* Perform the llseek(ls_fd, offset, whence) system call. */
register struct filp *rfilp;
u64_t pos, newpos;
int r = OK, seekfd, seekwhence;
long off_hi, off_lo;
seekfd = job_m_in.ls_fd;
seekwhence = job_m_in.whence;
off_hi = job_m_in.offset_high;
off_lo = job_m_in.offset_lo;
int r = OK;
long off_hi = ex64hi(offset);
/* Check to see if the file descriptor is valid. */
if ( (rfilp = get_filp(seekfd, VNODE_READ)) == NULL) return(err_code);
if ( (rfilp = get_filp2(rfp, seekfd, VNODE_READ, userreq)) == NULL) {
printf("actual_llseek: get_filp2 failed for fp %d fd %d userreq %d err %d\n",
rfp->fp_endpoint, seekfd, userreq, err_code);
return(err_code);
}
/* No lseek on pipes. */
if (S_ISFIFO(rfilp->filp_vno->v_mode)) {
@ -679,7 +683,7 @@ int do_llseek(message *m_out)
default: unlock_filp(rfilp); return(EINVAL);
}
newpos = add64(pos, make64(off_lo, off_hi));
newpos = pos + offset;
/* Check for overflow. */
if ((off_hi > 0) && cmp64(newpos, pos) < 0)
@ -704,24 +708,30 @@ int do_llseek(message *m_out)
return(r);
}
int do_llseek(message *m_out)
{
return actual_llseek(fp, m_out, job_m_in.ls_fd, job_m_in.whence,
make64(job_m_in.offset_lo, job_m_in.offset_high), 1);
}
/*===========================================================================*
* do_close *
*===========================================================================*/
int do_close(message *UNUSED(m_out))
{
/* Perform the close(fd) system call. */
scratch(fp).file.fd_nr = job_m_in.fd;
return close_fd(fp, scratch(fp).file.fd_nr);
int thefd = job_m_in.fd;
return close_fd(fp, thefd, 1);
}
/*===========================================================================*
* close_fd *
*===========================================================================*/
int close_fd(rfp, fd_nr)
int close_fd(rfp, fd_nr, user_request)
struct fproc *rfp;
int fd_nr;
int user_request;
{
/* Perform the close(fd) system call. */
register struct filp *rfilp;
@ -730,11 +740,19 @@ int fd_nr;
int lock_count;
/* First locate the vnode that belongs to the file descriptor. */
if ( (rfilp = get_filp2(rfp, fd_nr, VNODE_OPCL)) == NULL) return(err_code);
if ( (rfilp = get_filp2(rfp, fd_nr, VNODE_WRITE, user_request)) == NULL) {
return(err_code);
}
vp = rfilp->filp_vno;
close_filp(rfilp);
/* first, make all future get_filp2()'s fail; otherwise
* we might try to close the same fd in different threads
*/
rfp->fp_filp[fd_nr] = NULL;
close_filp(rfilp);
FD_CLR(fd_nr, &rfp->fp_cloexec_set);
FD_CLR(fd_nr, &rfp->fp_filp_inuse);

View File

@ -101,7 +101,7 @@ static int create_pipe(int fil_des[2], int flags)
/* Acquire two file descriptors. */
rfp = fp;
if ((r = get_fd(0, R_BIT, &fil_des[0], &fil_ptr0)) != OK) {
if ((r = get_fd(fp, 0, R_BIT, &fil_des[0], &fil_ptr0, 1)) != OK) {
unlock_vnode(vp);
unlock_vmnt(vmp);
return(r);
@ -109,7 +109,7 @@ static int create_pipe(int fil_des[2], int flags)
rfp->fp_filp[fil_des[0]] = fil_ptr0;
FD_SET(fil_des[0], &rfp->fp_filp_inuse);
fil_ptr0->filp_count = 1; /* mark filp in use */
if ((r = get_fd(0, W_BIT, &fil_des[1], &fil_ptr1)) != OK) {
if ((r = get_fd(fp, 0, W_BIT, &fil_des[1], &fil_ptr1, 1)) != OK) {
rfp->fp_filp[fil_des[0]] = NULL;
FD_CLR(fil_des[0], &rfp->fp_filp_inuse);
fil_ptr0->filp_count = 0; /* mark filp free */
@ -601,7 +601,7 @@ void unpause(endpoint_t proc_e)
}
fild = scratch(rfp).file.fd_nr;
if (fild < 0 || fild >= OPEN_MAX)
if (fild < 0 || fild >= FDS_PER_PROCESS)
panic("file descriptor out-of-range");
f = rfp->fp_filp[fild];
dev = (dev_t) f->filp_vno->v_sdev; /* device hung on */

View File

@ -86,10 +86,11 @@ void check_filp_locks(void);
void check_filp_locks_by_me(void);
void init_filps(void);
struct filp *find_filp(struct vnode *vp, mode_t bits);
int get_fd(int start, mode_t bits, int *k, struct filp **fpt);
int get_fd(struct fproc *rfp, int start, mode_t bits, int *k,
struct filp **fpt, int user);
struct filp *get_filp(int fild, tll_access_t locktype);
struct filp *get_filp2(struct fproc *rfp, int fild, tll_access_t
locktype);
locktype, int userrequest);
void lock_filp(struct filp *filp, tll_access_t locktype);
void unlock_filp(struct filp *filp);
void unlock_filps(struct filp *filp1, struct filp *filp2);
@ -143,6 +144,7 @@ int do_fsync(message *m_out);
void pm_reboot(void);
int do_svrctl(message *m_out);
int do_getsysinfo(void);
int do_vm_call(message *m_out);
int pm_dumpcore(endpoint_t proc_e, int sig, vir_bytes exe_name);
void * ds_event(void *arg);
@ -159,9 +161,9 @@ void unmount_all(int force);
/* open.c */
int do_close(message *m_out);
int close_fd(struct fproc *rfp, int fd_nr);
int close_fd(struct fproc *rfp, int fd_nr, int flag);
void close_reply(void);
int common_open(char path[PATH_MAX], int oflags, mode_t omode);
int common_open(char path[PATH_MAX], int oflags, mode_t omode, int userfd);
int do_creat(void);
int do_lseek(message *m_out);
int do_llseek(message *m_out);
@ -169,6 +171,9 @@ int do_mknod(message *m_out);
int do_mkdir(message *m_out);
int do_open(message *m_out);
int do_slink(message *m_out);
int actual_lseek(message *m_out, int seekfd, int seekwhence, off_t offset);
int actual_llseek(struct fproc *rfp, message *m_out, int seekfd,
int seekwhence, u64_t offset, int userrequest);
int do_vm_open(void);
int do_vm_close(void);
@ -213,8 +218,10 @@ void lock_bsf(void);
void unlock_bsf(void);
void check_bsf_lock(void);
int do_read_write_peek(int rw_flag, int fd, char *buf, size_t bytes);
int read_write(int rw_flag, struct filp *f, char *buffer, size_t nbytes,
endpoint_t for_e);
int actual_read_write_peek(struct fproc *rfp, int rw_flag, int fd, char *buf,
size_t bytes, int userreq);
int read_write(struct fproc *rfp, int rw_flag, struct filp *f, char *buffer,
size_t nbytes, endpoint_t for_e);
int rw_pipe(int rw_flag, endpoint_t usr, struct filp *f, char *buf,
size_t req_size);

View File

@ -83,9 +83,10 @@ void check_bsf_lock(void)
}
/*===========================================================================*
* do_read_write_peek *
* actual_read_write_peek *
*===========================================================================*/
int do_read_write_peek(int rw_flag, int io_fd, char *io_buf, size_t io_nbytes)
int actual_read_write_peek(struct fproc *rfp, int rw_flag, int io_fd,
char *io_buf, size_t io_nbytes, int userreq)
{
/* Perform read(fd, buffer, nbytes) or write(fd, buffer, nbytes) call. */
struct filp *f;
@ -95,37 +96,48 @@ int do_read_write_peek(int rw_flag, int io_fd, char *io_buf, size_t io_nbytes)
if(rw_flag == WRITING) ro = 0;
scratch(fp).file.fd_nr = io_fd;
scratch(fp).io.io_buffer = io_buf;
scratch(fp).io.io_nbytes = io_nbytes;
scratch(rfp).file.fd_nr = io_fd;
scratch(rfp).io.io_buffer = io_buf;
scratch(rfp).io.io_nbytes = io_nbytes;
locktype = ro ? VNODE_READ : VNODE_WRITE;
if ((f = get_filp(scratch(fp).file.fd_nr, locktype)) == NULL)
locktype = rw_flag == WRITING ? VNODE_WRITE : VNODE_READ;
if ((f = get_filp2(rfp, scratch(rfp).file.fd_nr, locktype, userreq)) == NULL)
return(err_code);
assert(f->filp_count > 0);
if (((f->filp_mode) & (ro ? R_BIT : W_BIT)) == 0) {
unlock_filp(f);
return(f->filp_mode == FILP_CLOSED ? EIO : EBADF);
}
if (scratch(fp).io.io_nbytes == 0) {
if (scratch(rfp).io.io_nbytes == 0) {
unlock_filp(f);
return(0); /* so char special files need not check for 0*/
}
r = read_write(rw_flag, f, scratch(fp).io.io_buffer, scratch(fp).io.io_nbytes,
who_e);
r = read_write(rfp, rw_flag, f, scratch(rfp).io.io_buffer,
scratch(rfp).io.io_nbytes, who_e);
unlock_filp(f);
return(r);
}
/*===========================================================================*
* do_read_write_peek *
*===========================================================================*/
int do_read_write_peek(int rw_flag, int io_fd, char *io_buf, size_t io_nbytes)
{
return actual_read_write_peek(fp, rw_flag, io_fd, io_buf, io_nbytes, 1);
}
/*===========================================================================*
* read_write *
*===========================================================================*/
int read_write(int rw_flag, struct filp *f, char *buf, size_t size,
endpoint_t for_e)
int read_write(struct fproc *rfp, int rw_flag, struct filp *f,
char *buf, size_t size, endpoint_t for_e)
{
register struct vnode *vp;
u64_t position, res_pos, new_pos;
u64_t position, res_pos;
unsigned int cum_io, cum_io_incr, res_cum_io;
int op, r;
@ -141,17 +153,23 @@ int read_write(int rw_flag, struct filp *f, char *buf, size_t size,
op = (rw_flag == READING ? VFS_DEV_READ : VFS_DEV_WRITE);
if (S_ISFIFO(vp->v_mode)) { /* Pipes */
if (fp->fp_cum_io_partial != 0) {
if (rfp->fp_cum_io_partial != 0) {
panic("VFS: read_write: fp_cum_io_partial not clear");
}
if(rw_flag == PEEKING) return EINVAL;
if(rw_flag == PEEKING) {
printf("read_write: peek on pipe makes no sense\n");
return EINVAL;
}
r = rw_pipe(rw_flag, for_e, f, buf, size);
} else if (S_ISCHR(vp->v_mode)) { /* Character special files. */
dev_t dev;
int suspend_reopen;
int op = (rw_flag == READING ? VFS_DEV_READ : VFS_DEV_WRITE);
if(rw_flag == PEEKING) return EINVAL;
if(rw_flag == PEEKING) {
printf("read_write: peek on char device makes no sense\n");
return EINVAL;
}
if (vp->v_sdev == NO_DEV)
panic("VFS: read_write tries to access char dev NO_DEV");
@ -170,15 +188,17 @@ int read_write(int rw_flag, struct filp *f, char *buf, size_t size,
if (vp->v_sdev == NO_DEV)
panic("VFS: read_write tries to access block dev NO_DEV");
if(rw_flag == PEEKING) return EINVAL;
lock_bsf();
r = req_breadwrite(vp->v_bfs_e, for_e, vp->v_sdev, position, size,
buf, rw_flag, &res_pos, &res_cum_io);
if (r == OK) {
position = res_pos;
cum_io += res_cum_io;
if(rw_flag == PEEKING) {
r = req_bpeek(vp->v_bfs_e, vp->v_sdev, position, size);
} else {
r = req_breadwrite(vp->v_bfs_e, for_e, vp->v_sdev,
position, size, buf, rw_flag, &res_pos, &res_cum_io);
if (r == OK) {
position = res_pos;
cum_io += res_cum_io;
}
}
unlock_bsf();
@ -189,16 +209,21 @@ int read_write(int rw_flag, struct filp *f, char *buf, size_t size,
}
/* Issue request */
r = req_readwrite(vp->v_fs_e, vp->v_inode_nr, position, rw_flag, for_e,
buf, size, &new_pos, &cum_io_incr);
if(rw_flag == PEEKING) {
r = req_peek(vp->v_fs_e, vp->v_inode_nr, position, size);
} else {
u64_t new_pos;
r = req_readwrite(vp->v_fs_e, vp->v_inode_nr, position,
rw_flag, for_e, buf, size, &new_pos, &cum_io_incr);
if (r >= 0) {
if (ex64hi(new_pos))
panic("read_write: bad new pos");
if (r >= 0) {
if (ex64hi(new_pos))
panic("read_write: bad new pos");
position = new_pos;
cum_io += cum_io_incr;
}
position = new_pos;
cum_io += cum_io_incr;
}
}
}
/* On write, update file size and access time. */
@ -220,7 +245,7 @@ int read_write(int rw_flag, struct filp *f, char *buf, size_t size,
* generate s SIGPIPE signal.
*/
if (!(f->filp_flags & O_NOSIGPIPE)) {
sys_kill(fp->fp_endpoint, SIGPIPE);
sys_kill(rfp->fp_endpoint, SIGPIPE);
}
}
@ -292,6 +317,8 @@ size_t req_size;
vp = f->filp_vno;
position = cvu64(0); /* Not actually used */
assert(rw_flag == READING || rw_flag == WRITING);
/* fp->fp_cum_io_partial is only nonzero when doing partial writes */
cum_io = fp->fp_cum_io_partial;

View File

@ -32,8 +32,8 @@ static struct selectentry {
fd_set readfds, writefds, errorfds;
fd_set ready_readfds, ready_writefds, ready_errorfds;
fd_set *vir_readfds, *vir_writefds, *vir_errorfds;
struct filp *filps[OPEN_MAX];
int type[OPEN_MAX];
struct filp *filps[FDS_PER_PROCESS];
int type[FDS_PER_PROCESS];
int nfds, nreadyfds;
int error;
char block;
@ -103,7 +103,7 @@ int do_select(message *UNUSED(m_out))
vtimeout = (vir_bytes) job_m_in.SEL_TIMEOUT;
/* Sane amount of file descriptors? */
if (nfds < 0 || nfds > OPEN_MAX) return(EINVAL);
if (nfds < 0 || nfds > FDS_PER_PROCESS) return(EINVAL);
/* Find a slot to store this select request */
for (s = 0; s < MAXSELECTS; s++)
@ -543,7 +543,7 @@ static int copy_fdsets(struct selectentry *se, int nfds, int direction)
endpoint_t src_e, dst_e;
fd_set *src_fds, *dst_fds;
if (nfds < 0 || nfds > OPEN_MAX)
if (nfds < 0 || nfds > FDS_PER_PROCESS)
panic("select copy_fdsets: nfds wrong: %d", nfds);
/* Only copy back as many bits as the user expects. */

View File

@ -132,6 +132,7 @@ int (*call_vec[])(message *m_out) = {
no_sys, /* 114 = (clock_getres) */
no_sys, /* 115 = (clock_gettime) */
no_sys, /* 116 = (clock_settime) */
do_vm_call, /* 117 = call from vm */
};
/* This should not fail with "array size is negative": */
extern int dummy[sizeof(call_vec) == NCALLS * sizeof(call_vec[0]) ? 1 : -1];

View File

@ -16,9 +16,9 @@ static int init = 0;
static mthread_attr_t tattr;
#ifdef MKCOVERAGE
# define TH_STACKSIZE (10 * 1024)
# define TH_STACKSIZE (40 * 1024)
#else
# define TH_STACKSIZE (7 * 1024)
# define TH_STACKSIZE (28 * 1024)
#endif
#define ASSERTW(w) assert((w) == &sys_worker || (w) == &dl_worker || \

View File

@ -92,6 +92,7 @@ typedef __off_t off_t; /* file offset */
#define MAP_FIXED 0x0200 /* require mapping to happen at hint */
#define MAP_THIRDPARTY 0x0400 /* perform on behalf of any process */
#define MAP_UNINITIALIZED 0x0800 /* do not clear memory */
#define MAP_FILE 0x1000 /* it's a file */
/*
* Error indicator returned by mmap(2)