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/lib/libexec/exec_elf.c b/lib/libexec/exec_elf.c index 24bfed966..eec744e94 100644 --- a/lib/libexec/exec_elf.c +++ b/lib/libexec/exec_elf.c @@ -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) { 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/pfs/const.h b/servers/pfs/const.h index f89a239be..edc8e989f 100644 --- a/servers/pfs/const.h +++ b/servers/pfs/const.h @@ -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). diff --git a/servers/pfs/glo.h b/servers/pfs/glo.h index c39a7581f..fd0db9075 100644 --- a/servers/pfs/glo.h +++ b/servers/pfs/glo.h @@ -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 diff --git a/servers/pfs/inode.c b/servers/pfs/inode.c index 333d56567..b6a508649 100644 --- a/servers/pfs/inode.c +++ b/servers/pfs/inode.c @@ -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); } diff --git a/servers/pfs/inode.h b/servers/pfs/inode.h index 19e582593..897ba7aca 100644 --- a/servers/pfs/inode.h +++ b/servers/pfs/inode.h @@ -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; diff --git a/servers/pfs/main.c b/servers/pfs/main.c index 7d8d71e0b..f88fe0cb2 100644 --- a/servers/pfs/main.c +++ b/servers/pfs/main.c @@ -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; } diff --git a/servers/pfs/super.c b/servers/pfs/super.c index 958fa2a6b..dc022946d 100644 --- a/servers/pfs/super.c +++ b/servers/pfs/super.c @@ -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; 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..4ff81ee07 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,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(); } + 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..43952f343 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 == 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; 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)