From 35a83eadc02b6c74684bc61b1af5aaa157d04e7b Mon Sep 17 00:00:00 2001 From: Ben Gras Date: Tue, 7 May 2013 12:41:07 +0000 Subject: [PATCH] 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 --- commands/service/parse.c | 1 + etc/system.conf | 3 +- include/minix/callnr.h | 4 +- include/minix/com.h | 9 ++- include/minix/vm.h | 8 ++ lib/libc/sys-minix/mmap.c | 26 +++++++ servers/is/inc.h | 2 + servers/pm/table.c | 1 + servers/procfs/inc.h | 2 + servers/vfs/const.h | 11 ++- servers/vfs/coredump.c | 2 +- servers/vfs/exec.c | 60 ++++++++++++++- servers/vfs/fdset.h | 11 +++ servers/vfs/filedes.c | 36 +++++---- servers/vfs/fproc.h | 3 +- servers/vfs/fs.h | 7 +- servers/vfs/main.c | 5 +- servers/vfs/misc.c | 153 ++++++++++++++++++++++++++++++++++++-- servers/vfs/open.c | 78 +++++++++++-------- servers/vfs/pipe.c | 6 +- servers/vfs/proto.h | 19 +++-- servers/vfs/read.c | 91 +++++++++++++++-------- servers/vfs/select.c | 8 +- servers/vfs/table.c | 1 + servers/vfs/worker.c | 4 +- sys/sys/mman.h | 1 + 26 files changed, 436 insertions(+), 116 deletions(-) create mode 100644 servers/vfs/fdset.h diff --git a/commands/service/parse.c b/commands/service/parse.c index ea805a073..2808da172 100644 --- a/commands/service/parse.c +++ b/commands/service/parse.c @@ -734,6 +734,7 @@ struct { "PROCCTL", VM_PROCCTL }, { "MAPCACHEPAGE", VM_MAPCACHEPAGE }, { "SETCACHEPAGE", VM_SETCACHEPAGE }, + { "VFS_MMAP", VM_VFS_MMAP }, { NULL, 0 }, }; diff --git a/etc/system.conf b/etc/system.conf index 496888114..6050d210d 100644 --- a/etc/system.conf +++ b/etc/system.conf @@ -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 diff --git a/include/minix/callnr.h b/include/minix/callnr.h index e38d881d8..0ec74931b 100644 --- a/include/minix/callnr.h +++ b/include/minix/callnr.h @@ -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. */ diff --git a/include/minix/com.h b/include/minix/com.h index 8af307b9f..08496d220 100644 --- a/include/minix/com.h +++ b/include/minix/com.h @@ -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 * diff --git a/include/minix/vm.h b/include/minix/vm.h index 698905954..6ed245e08 100644 --- a/include/minix/vm.h +++ b/include/minix/vm.h @@ -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. diff --git a/lib/libc/sys-minix/mmap.c b/lib/libc/sys-minix/mmap.c index 4a3de773e..f213f8fbf 100644 --- a/lib/libc/sys-minix/mmap.c +++ b/lib/libc/sys-minix/mmap.c @@ -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; diff --git a/servers/is/inc.h b/servers/is/inc.h index fe5025e67..5186b50a3 100644 --- a/servers/is/inc.h +++ b/servers/is/inc.h @@ -6,6 +6,8 @@ #define _SYSTEM 1 /* get OK and negative error codes */ +#include "../vfs/fdset.h" + #include #include #include diff --git a/servers/pm/table.c b/servers/pm/table.c index 258ed1501..d1c2075a1 100644 --- a/servers/pm/table.c +++ b/servers/pm/table.c @@ -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]; diff --git a/servers/procfs/inc.h b/servers/procfs/inc.h index ae411730f..5316847c3 100644 --- a/servers/procfs/inc.h +++ b/servers/procfs/inc.h @@ -3,6 +3,8 @@ #define _SYSTEM 1 +#include "vfs/fdset.h" + #include #include #include diff --git a/servers/vfs/const.h b/servers/vfs/const.h index 6c2ff41cd..46dd5b03c 100644 --- a/servers/vfs/const.h +++ b/servers/vfs/const.h @@ -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 */ diff --git a/servers/vfs/coredump.c b/servers/vfs/coredump.c index 9b5d24573..578d43df5 100644 --- a/servers/vfs/coredump.c +++ b/servers/vfs/coredump.c @@ -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); } /*===========================================================================* diff --git a/servers/vfs/exec.c b/servers/vfs/exec.c index ce00e56c8..2ad9826dc 100644 --- a/servers/vfs/exec.c +++ b/servers/vfs/exec.c @@ -16,6 +16,7 @@ #include "fs.h" #include +#include #include #include #include @@ -30,6 +31,7 @@ #include "path.h" #include "param.h" #include "vnode.h" +#include "file.h" #include #include #include @@ -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); } /*===========================================================================* diff --git a/servers/vfs/fdset.h b/servers/vfs/fdset.h new file mode 100644 index 000000000..80c8f6384 --- /dev/null +++ b/servers/vfs/fdset.h @@ -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 + +#endif diff --git a/servers/vfs/filedes.c b/servers/vfs/filedes.c index 1ccdb8eb9..2e404f16e 100644 --- a/servers/vfs/filedes.c +++ b/servers/vfs/filedes.c @@ -15,12 +15,13 @@ * the receiver. */ +#include "fs.h" + #include #include #include #include #include -#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)) { diff --git a/servers/vfs/fproc.h b/servers/vfs/fproc.h index 9ef7acbd0..dfab0afe4 100644 --- a/servers/vfs/fproc.h +++ b/servers/vfs/fproc.h @@ -2,6 +2,7 @@ #define __VFS_FPROC_H__ #include "threads.h" +#include "fdset.h" #include #include @@ -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 */ diff --git a/servers/vfs/fs.h b/servers/vfs/fs.h index 3c95e26d5..d5fbf0f5f 100644 --- a/servers/vfs/fs.h +++ b/servers/vfs/fs.h @@ -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 /* MUST be first */ +#include + #include #include #include @@ -23,7 +27,6 @@ #include #include -#include "const.h" #include "dmap.h" #include "proto.h" #include "threads.h" diff --git a/servers/vfs/main.c b/servers/vfs/main.c index d18cb752f..437e794de 100644 --- a/servers/vfs/main.c +++ b/servers/vfs/main.c @@ -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' */ diff --git a/servers/vfs/misc.c b/servers/vfs/misc.c index 44d9d53b7..59745e6dc 100644 --- a/servers/vfs/misc.c +++ b/servers/vfs/misc.c @@ -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,140 @@ 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); + + 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); + + /* 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 +531,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 +575,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 +612,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 +819,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 +832,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 +845,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 +904,4 @@ void panic_hook(void) printf("VFS mthread stacktraces:\n"); mthread_stacktraces(); } + diff --git a/servers/vfs/open.c b/servers/vfs/open.c index 36b722660..3a4b1bfca 100644 --- a/servers/vfs/open.c +++ b/servers/vfs/open.c @@ -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); diff --git a/servers/vfs/pipe.c b/servers/vfs/pipe.c index a6cc0f9e0..02dc3d684 100644 --- a/servers/vfs/pipe.c +++ b/servers/vfs/pipe.c @@ -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 */ diff --git a/servers/vfs/proto.h b/servers/vfs/proto.h index a2fe8728b..83c76282b 100644 --- a/servers/vfs/proto.h +++ b/servers/vfs/proto.h @@ -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); diff --git a/servers/vfs/read.c b/servers/vfs/read.c index b278738f0..0f17708a9 100644 --- a/servers/vfs/read.c +++ b/servers/vfs/read.c @@ -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 == READING ? VNODE_READ : VNODE_WRITE; + 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; diff --git a/servers/vfs/select.c b/servers/vfs/select.c index 191b01ffc..98ce6f2c7 100644 --- a/servers/vfs/select.c +++ b/servers/vfs/select.c @@ -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. */ diff --git a/servers/vfs/table.c b/servers/vfs/table.c index 5fe5b817e..6aa4f734b 100644 --- a/servers/vfs/table.c +++ b/servers/vfs/table.c @@ -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]; diff --git a/servers/vfs/worker.c b/servers/vfs/worker.c index add1d3712..8b9f20f27 100644 --- a/servers/vfs/worker.c +++ b/servers/vfs/worker.c @@ -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 || \ diff --git a/sys/sys/mman.h b/sys/sys/mman.h index 2c37e14c4..c4d1f838a 100644 --- a/sys/sys/mman.h +++ b/sys/sys/mman.h @@ -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)