diff --git a/servers/is/inc.h b/servers/is/inc.h index 5186b50a3..fe5025e67 100644 --- a/servers/is/inc.h +++ b/servers/is/inc.h @@ -6,8 +6,6 @@ #define _SYSTEM 1 /* get OK and negative error codes */ -#include "../vfs/fdset.h" - #include #include #include diff --git a/servers/procfs/inc.h b/servers/procfs/inc.h index 5316847c3..ae411730f 100644 --- a/servers/procfs/inc.h +++ b/servers/procfs/inc.h @@ -3,8 +3,6 @@ #define _SYSTEM 1 -#include "vfs/fdset.h" - #include #include #include diff --git a/servers/vfs/Makefile b/servers/vfs/Makefile index 083a5675c..094a176c6 100644 --- a/servers/vfs/Makefile +++ b/servers/vfs/Makefile @@ -14,7 +14,7 @@ SRCS+= gcov.c CPPFLAGS+= -DUSE_COVERAGE .endif -CFLAGS+= -Wall -Wextra -Werror +CFLAGS+= -Wall -Wextra #-Werror DPADD+= ${LIBSYS} ${LIBTIMERS} ${LIBEXEC} LDADD+= -lsys -ltimers -lexec -lmthread diff --git a/servers/vfs/const.h b/servers/vfs/const.h index 46dd5b03c..7262aee70 100644 --- a/servers/vfs/const.h +++ b/servers/vfs/const.h @@ -1,13 +1,6 @@ #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 1024 /* # slots in filp table */ #define NR_LOCKS 8 /* # slots in the file locking table */ diff --git a/servers/vfs/exec.c b/servers/vfs/exec.c index 2ad9826dc..9e9b6d096 100644 --- a/servers/vfs/exec.c +++ b/servers/vfs/exec.c @@ -50,8 +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; + int vmfd; + int vmfd_used; }; static void lock_exec(void); @@ -202,9 +202,9 @@ static int vfs_memmap(struct exec_info *execi, flags |= MVM_WRITABLE; r = minix_vfs_mmap(execi->proc_e, foffset, len, - vp->v_dev, vp->v_inode_nr, vi->procfd, vaddr, clearend, flags); + vp->v_dev, vp->v_inode_nr, vi->vmfd, vaddr, clearend, flags); if(r == OK) { - vi->procfd_used = 1; + vi->vmfd_used = 1; } return r; @@ -233,15 +233,18 @@ int pm_exec(endpoint_t proc_e, vir_bytes path, size_t path_len, firstexec[PATH_MAX], finalexec[PATH_MAX]; struct lookup resolve; + struct fproc *vmfp = &fproc[VM_PROC_NR]; stackhook_t makestack = NULL; static int n; n++; + struct filp *newfilp = NULL; lock_exec(); + lock_proc(vmfp, 0); /* unset execi values are 0. */ memset(&execi, 0, sizeof(execi)); - execi.procfd = -1; + execi.vmfd = -1; /* passed from exec() libc code */ execi.userflags = user_exec_flags; @@ -312,7 +315,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, 1)) < 0) { + if((r = execi.elf_main_fd = common_open(finalexec, O_RDONLY, 0)) < 0) { printf("VFS: exec: dynamic: open main exec failed %s (%d)\n", fullpath, r); FAILCHECK(r); @@ -335,16 +338,22 @@ int pm_exec(endpoint_t proc_e, vir_bytes path, size_t path_len, Get_read_vp(execi, fullpath, 0, 0, &resolve, fp); } - /* We also want an FD so VM can mmap() the process in if possible. */ + /* We also want an FD for VM to 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) { + struct vnode *vp = execi.vp; + assert(vp); + if(vp->v_vmnt->m_haspeek && major(vp->v_dev) != MEMORY_MAJOR) { + int newfd = -1; + if(get_fd(vmfp, 0, R_BIT, &newfd, &newfilp) == OK) { + assert(newfd >= 0 && newfd < OPEN_MAX); + assert(!vmfp->fp_filp[newfd]); + newfilp->filp_count = 1; + newfilp->filp_vno = vp; + newfilp->filp_flags = O_RDONLY; + FD_SET(newfd, &vmfp->fp_filp_inuse); + vmfp->fp_filp[newfd] = newfilp; + /* dup_vnode(vp); */ + execi.vmfd = newfd; execi.args.memmap = vfs_memmap; } } @@ -402,15 +411,19 @@ int pm_exec(endpoint_t proc_e, vir_bytes path, size_t path_len, strlcpy(rfp->fp_name, execi.args.progname, PROC_NAME_LEN); pm_execfinal: - if (execi.vp != NULL) { + if(newfilp) unlock_filp(newfilp); + else if (execi.vp != NULL) { unlock_vnode(execi.vp); put_vnode(execi.vp); } - if(execi.procfd >= 0 && !execi.procfd_used) { - int r; - r = close_fd(rfp, execi.procfd, 0); + + if(execi.vmfd >= 0 && !execi.vmfd_used) { + if(OK != close_fd(vmfp, execi.vmfd)) { + printf("VFS: unexpected close fail of vm fd\n"); + } } + unlock_proc(vmfp); unlock_exec(); return(r); @@ -703,9 +716,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 < FDS_PER_PROCESS; i++) + for (i = 0; i < OPEN_MAX; i++) if ( FD_ISSET(i, &rfp->fp_cloexec_set)) - (void) close_fd(rfp, i, 0); + (void) close_fd(rfp, i); } /*===========================================================================* diff --git a/servers/vfs/fdset.h b/servers/vfs/fdset.h deleted file mode 100644 index 80c8f6384..000000000 --- a/servers/vfs/fdset.h +++ /dev/null @@ -1,11 +0,0 @@ -#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 2e404f16e..081a872f7 100644 --- a/servers/vfs/filedes.c +++ b/servers/vfs/filedes.c @@ -149,7 +149,7 @@ void init_filps(void) * get_fd * *===========================================================================*/ int get_fd(struct fproc *rfp, int start, mode_t bits, int *k, - struct filp **fpt, int userfd) + struct filp **fpt) { /* 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() @@ -158,7 +158,7 @@ int get_fd(struct fproc *rfp, int start, mode_t bits, int *k, register struct filp *f; register int i; - int limit = userfd ? OPEN_MAX : FDS_PER_PROCESS; + int limit = OPEN_MAX; /* Search the fproc fp_filp table for a free file descriptor. */ for (i = start; i < limit; i++) { @@ -206,22 +206,21 @@ 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, 1); + return get_filp2(fp, fild, locktype); } /*===========================================================================* * get_filp2 * *===========================================================================*/ -struct filp *get_filp2(rfp, fild, locktype, userrequest) +struct filp *get_filp2(rfp, fild, locktype) 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; + int fdlimit = OPEN_MAX; filp = NULL; if (fild < 0 || fild >= fdlimit) { @@ -275,7 +274,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 < FDS_PER_PROCESS; fd++) { + for (fd = 0; fd < OPEN_MAX; fd++) { if(fproc[f].fp_filp[fd] && fproc[f].fp_filp[fd] == rfilp) { fproc[f].fp_filp[fd] = NULL; n++; @@ -441,7 +440,7 @@ int fd; if (isokendpt(ep, &slot) != OK) return(NULL); - rfilp = get_filp2(&fproc[slot], fd, VNODE_READ, 1); + rfilp = get_filp2(&fproc[slot], fd, VNODE_READ); return(rfilp); } @@ -504,7 +503,7 @@ filp_id_t cfilp; rfp = &fproc[slot]; /* Find an open slot in fp_filp */ - for (fd = 0; fd < FDS_PER_PROCESS; fd++) { + for (fd = 0; fd < OPEN_MAX; 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 dfab0afe4..35251a48d 100644 --- a/servers/vfs/fproc.h +++ b/servers/vfs/fproc.h @@ -2,7 +2,6 @@ #define __VFS_FPROC_H__ #include "threads.h" -#include "fdset.h" #include #include @@ -21,7 +20,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[FDS_PER_PROCESS]; /* the file descriptor table */ + struct filp *fp_filp[OPEN_MAX]; /* 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 d5fbf0f5f..00e901653 100644 --- a/servers/vfs/fs.h +++ b/servers/vfs/fs.h @@ -6,9 +6,6 @@ */ #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 @@ -27,6 +24,7 @@ #include #include +#include "const.h" #include "dmap.h" #include "proto.h" #include "threads.h" diff --git a/servers/vfs/misc.c b/servers/vfs/misc.c index 4ff81ee07..0f9e7083c 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(fp, fcntl_argx, 0, &new_fd, NULL, 1)) == OK) { + else if ((r = get_fd(fp, fcntl_argx, 0, &new_fd, NULL)) == OK) { f->filp_count++; fp->fp_filp[new_fd] = f; FD_SET(new_fd, &fp->fp_filp_inuse); @@ -311,6 +311,56 @@ int do_fsync(message *UNUSED(m_out)) return(r); } +int dupvm(struct fproc *rfp, int pfd, int *vmfd, struct filp **newfilp) +{ + int result, procfd; + struct filp *f = NULL; + struct fproc *vmf = &fproc[VM_PROC_NR]; + + *newfilp = NULL; + + if ((f = get_filp2(rfp, pfd, VNODE_READ)) == NULL) { + printf("VFS dupvm: get_filp2 failed\n"); + return EBADF; + } + + if(!f->filp_vno->v_vmnt->m_haspeek) { + unlock_filp(f); + printf("VFS dupvm: no peek available\n"); + return EINVAL; + } + + assert(f->filp_vno); + assert(f->filp_vno->v_vmnt); + + 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); + unlock_filp(f); + return EINVAL; + } + + /* get free FD in VM */ + if((result=get_fd(vmf, 0, 0, &procfd, NULL)) != OK) { + unlock_filp(f); + printf("VFS dupvm: getfd failed\n"); + return result; + } + + *vmfd = procfd; + + f->filp_count++; + assert(f->filp_count > 0); + vmf->fp_filp[procfd] = f; + + /* mmap FD's are inuse */ + FD_SET(procfd, &vmf->fp_filp_inuse); + + *newfilp = f; + + return OK; +} + /*===========================================================================* * do_vm_call * *===========================================================================*/ @@ -336,46 +386,31 @@ int do_vm_call(message *m_out) if(job_m_in.m_source != VM_PROC_NR) return ENOSYS; - okendpt(ep, &slot); + if(isokendpt(ep, &slot) != OK) rfp = NULL; + else rfp = &fproc[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; + + if(!rfp) { + printf("VFS: why isn't ep %d here?!\n", ep); + result = ESRCH; goto reqdone; } - assert(f->filp_vno); - assert(f->filp_vno->v_vmnt); - - if(!f->filp_vno->v_vmnt->m_haspeek) { - result = EINVAL; + if((result = dupvm(rfp, req_fd, &procfd, &f)) != OK) { + printf("vfs: dupvm failed\n"); 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; @@ -391,24 +426,16 @@ int do_vm_call(message *m_out) 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); + result = close_fd(fp, req_fd); if(result != OK) { printf("VFS: VM fd close for fd %d, %d (%d)\n", - req_fd, rfp->fp_endpoint, result); + req_fd, fp->fp_endpoint, result); } break; } @@ -416,15 +443,12 @@ int do_vm_call(message *m_out) { message dummy_out; - result = actual_llseek(rfp, &dummy_out, req_fd, - SEEK_SET, offset, 0); + result = actual_llseek(fp, &dummy_out, req_fd, + SEEK_SET, offset); - 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); + if(result == OK) { + result = actual_read_write_peek(fp, PEEKING, + req_fd, NULL, length); } break; @@ -438,8 +462,6 @@ reqdone: if(f) unlock_filp(f); - unlock_proc(rfp); - /* fp is VM still. */ assert(fp == vmf); m_out->VMV_ENDPOINT = ep; @@ -535,7 +557,7 @@ void pm_fork(endpoint_t pproc, endpoint_t cproc, pid_t cpid) cp = &fproc[childno]; pp = &fproc[parentno]; - for (i = 0; i < FDS_PER_PROCESS; i++) + for (i = 0; i < OPEN_MAX; i++) if (cp->fp_filp[i] != NULL) cp->fp_filp[i]->filp_count++; /* Fill in new process and endpoint id. */ @@ -579,8 +601,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 < FDS_PER_PROCESS; i++) { - (void) close_fd(exiter, i, 0); + for (i = 0; i < OPEN_MAX; i++) { + (void) close_fd(exiter, i); } /* Release root and working directories. */ @@ -616,7 +638,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 < FDS_PER_PROCESS; i++) { + for (i = 0; i < OPEN_MAX; i++) { if ((rfilp = rfp->fp_filp[i]) == NULL) continue; if (rfilp->filp_mode == FILP_CLOSED) continue; vp = rfilp->filp_vno; @@ -837,7 +859,7 @@ int pm_dumpcore(endpoint_t proc_e, int csig, vir_bytes exe_name) /* open core file */ 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); + core_fd = common_open(core_path, O_WRONLY | O_CREAT | O_TRUNC, CORE_MODE); if (core_fd < 0) { r = core_fd; goto core_exit; } /* get process' name */ @@ -849,7 +871,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, 0); /* ignore failure, we're exiting anyway */ + (void) close_fd(fp, core_fd); /* ignore failure, we're exiting anyway */ core_exit: if(csig) diff --git a/servers/vfs/open.c b/servers/vfs/open.c index 3a4b1bfca..240444537 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, 1); + return common_open(fullpath, open_mode, create_mode); } /*===========================================================================* * common_open * *===========================================================================*/ -int common_open(char path[PATH_MAX], int oflags, mode_t omode, int userfd) +int common_open(char path[PATH_MAX], int oflags, mode_t omode) { /* Common code from do_creat and do_open. */ int b, r, exist = TRUE, major_dev; @@ -90,7 +90,7 @@ int common_open(char path[PATH_MAX], int oflags, mode_t omode, int userfd) struct vmnt *vmp; struct dmap *dp; struct lookup resolve; - int start = userfd ? 0 : SYSTEM_FDSTART; + int start = 0; /* Remap the bottom two bits of oflags. */ bits = (mode_t) mode_map[oflags & O_ACCMODE]; @@ -98,7 +98,7 @@ int common_open(char path[PATH_MAX], int oflags, mode_t omode, int userfd) /* See if file descriptor and filp slots are available. */ if ((r = get_fd(fp, start, bits, &(scratch(fp).file.fd_nr), - &filp, userfd)) != OK) + &filp)) != OK) return(r); lookup_init(&resolve, path, PATH_NOFLAGS, &vmp, &vp); @@ -654,7 +654,7 @@ int do_lseek(message *m_out) * actual_llseek * *===========================================================================*/ int actual_llseek(struct fproc *rfp, message *m_out, int seekfd, int seekwhence, - u64_t offset, int userreq) + u64_t offset) { /* Perform the llseek(ls_fd, offset, whence) system call. */ register struct filp *rfilp; @@ -663,9 +663,7 @@ int actual_llseek(struct fproc *rfp, message *m_out, int seekfd, int seekwhence, long off_hi = ex64hi(offset); /* Check to see if the file descriptor is valid. */ - 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); + if ( (rfilp = get_filp2(rfp, seekfd, VNODE_READ)) == NULL) { return(err_code); } @@ -711,7 +709,7 @@ int actual_llseek(struct fproc *rfp, message *m_out, int seekfd, int seekwhence, 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); + make64(job_m_in.offset_lo, job_m_in.offset_high)); } /*===========================================================================* @@ -721,17 +719,16 @@ int do_close(message *UNUSED(m_out)) { /* Perform the close(fd) system call. */ int thefd = job_m_in.fd; - return close_fd(fp, thefd, 1); + return close_fd(fp, thefd); } /*===========================================================================* * close_fd * *===========================================================================*/ -int close_fd(rfp, fd_nr, user_request) +int close_fd(rfp, fd_nr) struct fproc *rfp; int fd_nr; -int user_request; { /* Perform the close(fd) system call. */ register struct filp *rfilp; @@ -740,7 +737,7 @@ int user_request; int lock_count; /* First locate the vnode that belongs to the file descriptor. */ - if ( (rfilp = get_filp2(rfp, fd_nr, VNODE_WRITE, user_request)) == NULL) { + if ( (rfilp = get_filp2(rfp, fd_nr, VNODE_WRITE)) == NULL) { return(err_code); } diff --git a/servers/vfs/pipe.c b/servers/vfs/pipe.c index 02dc3d684..7870d7ae1 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(fp, 0, R_BIT, &fil_des[0], &fil_ptr0, 1)) != OK) { + if ((r = get_fd(fp, 0, R_BIT, &fil_des[0], &fil_ptr0)) != 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(fp, 0, W_BIT, &fil_des[1], &fil_ptr1, 1)) != OK) { + if ((r = get_fd(fp, 0, W_BIT, &fil_des[1], &fil_ptr1)) != 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 >= FDS_PER_PROCESS) + if (fild < 0 || fild >= OPEN_MAX) 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 83c76282b..339949042 100644 --- a/servers/vfs/proto.h +++ b/servers/vfs/proto.h @@ -87,10 +87,9 @@ void check_filp_locks_by_me(void); void init_filps(void); struct filp *find_filp(struct vnode *vp, mode_t bits); int get_fd(struct fproc *rfp, int start, mode_t bits, int *k, - struct filp **fpt, int user); + struct filp **fpt); struct filp *get_filp(int fild, tll_access_t locktype); -struct filp *get_filp2(struct fproc *rfp, int fild, tll_access_t - locktype, int userrequest); +struct filp *get_filp2(struct fproc *rfp, int fild, tll_access_t locktype); 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); @@ -147,6 +146,7 @@ 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); +int dupvm(struct fproc *fp, int pfd, int *vmfd, struct filp **f); /* mount.c */ int do_fsready(message *m_out); @@ -161,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 flag); +int close_fd(struct fproc *rfp, int fd_nr); void close_reply(void); -int common_open(char path[PATH_MAX], int oflags, mode_t omode, int userfd); +int common_open(char path[PATH_MAX], int oflags, mode_t omode); int do_creat(void); int do_lseek(message *m_out); int do_llseek(message *m_out); @@ -173,7 +173,7 @@ 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 seekwhence, u64_t offset); int do_vm_open(void); int do_vm_close(void); @@ -219,7 +219,7 @@ 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 actual_read_write_peek(struct fproc *rfp, int rw_flag, int fd, char *buf, - size_t bytes, int userreq); + size_t bytes); 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, diff --git a/servers/vfs/read.c b/servers/vfs/read.c index 43952f343..57bf38615 100644 --- a/servers/vfs/read.c +++ b/servers/vfs/read.c @@ -86,7 +86,7 @@ void check_bsf_lock(void) * actual_read_write_peek * *===========================================================================*/ int actual_read_write_peek(struct fproc *rfp, int rw_flag, int io_fd, - char *io_buf, size_t io_nbytes, int userreq) + char *io_buf, size_t io_nbytes) { /* Perform read(fd, buffer, nbytes) or write(fd, buffer, nbytes) call. */ struct filp *f; @@ -101,7 +101,7 @@ int actual_read_write_peek(struct fproc *rfp, int rw_flag, int io_fd, scratch(rfp).io.io_nbytes = io_nbytes; locktype = rw_flag == WRITING ? VNODE_WRITE : VNODE_READ; - if ((f = get_filp2(rfp, scratch(rfp).file.fd_nr, locktype, userreq)) == NULL) + if ((f = get_filp2(rfp, scratch(rfp).file.fd_nr, locktype)) == NULL) return(err_code); assert(f->filp_count > 0); @@ -127,7 +127,7 @@ int actual_read_write_peek(struct fproc *rfp, int rw_flag, int io_fd, *===========================================================================*/ 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); + return actual_read_write_peek(fp, rw_flag, io_fd, io_buf, io_nbytes); } /*===========================================================================* diff --git a/servers/vfs/select.c b/servers/vfs/select.c index 98ce6f2c7..191b01ffc 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[FDS_PER_PROCESS]; - int type[FDS_PER_PROCESS]; + struct filp *filps[OPEN_MAX]; + int type[OPEN_MAX]; 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 > FDS_PER_PROCESS) return(EINVAL); + if (nfds < 0 || nfds > OPEN_MAX) 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 > FDS_PER_PROCESS) + if (nfds < 0 || nfds > OPEN_MAX) panic("select copy_fdsets: nfds wrong: %d", nfds); /* Only copy back as many bits as the user expects. */ diff --git a/servers/vfs/utility.c b/servers/vfs/utility.c index db2f831d6..687b53d95 100644 --- a/servers/vfs/utility.c +++ b/servers/vfs/utility.c @@ -122,8 +122,6 @@ int isokendpt_f(char *file, int line, endpoint_t endpoint, int *proc, failed = 1; } else if ((ke = fproc[*proc].fp_endpoint) != endpoint) { if(ke == NONE) { - printf("VFS %s:%d: endpoint (%d) points to NONE slot (%d)\n", - file, line, endpoint, *proc); assert(fproc[*proc].fp_pid == PID_FREE); } else { printf("VFS %s:%d: proc (%d) from endpoint (%d) doesn't match " diff --git a/servers/vm/exit.c b/servers/vm/exit.c index 686bec593..f287b327a 100644 --- a/servers/vm/exit.c +++ b/servers/vm/exit.c @@ -43,7 +43,6 @@ void clear_proc(struct vmproc *vmp) vmp->vm_bytecopies = 0; #endif vmp->vm_region_top = 0; - vmp->fdrefs = NULL; } /*===========================================================================* @@ -119,12 +118,10 @@ int do_procctl(message *msg) if(msg->m_source != RS_PROC_NR && msg->m_source != VFS_PROC_NR) return EPERM; - vmp->vm_flags |= VMF_EXECING; free_proc(vmp); if(pt_new(&vmp->vm_pt) != OK) panic("VMPPARAM_CLEAR: pt_new failed"); pt_bind(&vmp->vm_pt, vmp); - vmp->vm_flags &= ~VMF_EXECING; return OK; default: return EINVAL; diff --git a/servers/vm/fdref.c b/servers/vm/fdref.c index 4239ddd5d..d72c5faf0 100644 --- a/servers/vm/fdref.c +++ b/servers/vm/fdref.c @@ -30,6 +30,65 @@ #include "vm.h" #include "fdref.h" #include "vmproc.h" +#include "glo.h" + +static struct fdref *fdrefs; + +void fdref_sanitycheck(void) +{ + struct vmproc *vmp; + region_iter v_iter; + struct fdref *fr; + static int prevopen = 0; + int openfd = 0; + + for(fr = fdrefs; fr; fr = fr->next) { + struct fdref *fr2; + for(fr2 = fdrefs; fr2; fr2 = fr2->next) { + if(fr == fr2) continue; + if(fr->fd == fr2->fd) { + printf("equal fd omg\n"); + util_stacktrace(); + } + if(fr->ino == fr2->ino && fr->dev == fr2->dev) { + printf("equal metadata omg\n"); + util_stacktrace(); + } + } + openfd++; + } + + for(fr = fdrefs; fr; fr = fr->next) { + fr->counting = 0; + } + + for(vmp = vmproc; vmp < &vmproc[VMP_NR]; vmp++) { + struct vir_region *vr; + if(!(vmp->vm_flags & VMF_INUSE)) + continue; + region_start_iter_least(&vmp->vm_regions_avl, &v_iter); + while((vr = region_get_iter(&v_iter))) { + if(vr->def_memtype == &mem_type_mappedfile && vr->param.file.inited) { + vr->param.file.fdref->counting++; + } + region_incr_iter(&v_iter); + } + + } + + for(fr = fdrefs; fr; fr = fr->next) { + if(fr->counting != fr->refcount) { + printf("counting %d != refcount %d\n", + fr->counting, fr->refcount); + util_stacktrace(); + } + } + + if(prevopen != openfd && openfd > 100) { + printf("%d open\n", openfd); + prevopen = openfd; + } +} struct fdref *fdref_new(struct vmproc *owner, ino_t ino, dev_t dev, int fd) { @@ -38,12 +97,11 @@ struct fdref *fdref_new(struct vmproc *owner, ino_t ino, dev_t dev, int fd) if(!SLABALLOC(fdref)) return NULL; fdref->fd = fd; - fdref->owner = owner; fdref->refcount = 0; fdref->dev = dev; fdref->ino = ino; - fdref->next = owner->fdrefs; - owner->fdrefs = fdref; + fdref->next = fdrefs; + fdrefs = fdref; return fdref; } @@ -51,7 +109,6 @@ struct fdref *fdref_new(struct vmproc *owner, ino_t ino, dev_t dev, int fd) void fdref_ref(struct fdref *ref, struct vir_region *region) { assert(ref); - assert(ref->owner == region->parent); region->param.file.fdref = ref; ref->refcount++; } @@ -63,7 +120,6 @@ void fdref_deref(struct vir_region *region) assert(ref); assert(ref->refcount > 0); - assert(ref->owner == region->parent); fd = ref->fd; region->param.file.fdref = NULL; @@ -71,10 +127,10 @@ void fdref_deref(struct vir_region *region) assert(ref->refcount >= 0); if(ref->refcount > 0) return; - if(region->parent->fdrefs == ref) region->parent->fdrefs = ref->next; + if(fdrefs == ref) fdrefs = ref->next; else { struct fdref *r; - for(r = region->parent->fdrefs; r->next != ref; r = r->next) + for(r = fdrefs; r->next != ref; r = r->next) ; assert(r); assert(r->next == ref); @@ -83,11 +139,7 @@ void fdref_deref(struct vir_region *region) SLABFREE(ref); ref = NULL; - - if(region->parent->vm_flags & (VMF_EXITING|VMF_EXECING)) { - return; - } - + /* If the last reference has disappeared, free the * ref object and asynchronously close the fd in VFS. * @@ -95,34 +147,27 @@ void fdref_deref(struct vir_region *region) * unexpected, isn't a problem and can't be handled. VFS * will print a diagnostic. */ -#if 1 if(vfs_request(VMVFSREQ_FDCLOSE, fd, region->parent, 0, 0, NULL, NULL, NULL, 0) != OK) { panic("fdref_deref: could not send close request"); } -#endif } struct fdref *fdref_dedup_or_new(struct vmproc *owner, - ino_t ino, dev_t dev, int fd) + ino_t ino, dev_t dev, int fd, int mayclose) { struct fdref *fr; - for(fr = owner->fdrefs; fr; fr = fr->next) { - assert(fr->owner == owner); - if(fr->fd == fd) { - assert(ino == fr->ino); - assert(dev == fr->dev); - return fr; - } + for(fr = fdrefs; fr; fr = fr->next) { if(ino == fr->ino && dev == fr->dev) { - assert(fd != fr->fd); -#if 1 + if(fd == fr->fd) { + return fr; + } + if(!mayclose) continue; if(vfs_request(VMVFSREQ_FDCLOSE, fd, owner, 0, 0, NULL, NULL, NULL, 0) != OK) { printf("fdref_dedup_or_new: could not close\n"); } -#endif return fr; } } diff --git a/servers/vm/fdref.h b/servers/vm/fdref.h index ce919ffc8..603baf4e7 100644 --- a/servers/vm/fdref.h +++ b/servers/vm/fdref.h @@ -21,8 +21,8 @@ struct fdref { int refcount; dev_t dev; ino_t ino; - struct vmproc *owner; struct fdref *next; + int counting; /* sanity check */ } *fdref; #endif diff --git a/servers/vm/fork.c b/servers/vm/fork.c index 16c71be65..877ec7f7b 100644 --- a/servers/vm/fork.c +++ b/servers/vm/fork.c @@ -60,7 +60,6 @@ int do_fork(message *msg) /* The child is basically a copy of the parent. */ origpt = vmc->vm_pt; *vmc = *vmp; - vmc->fdrefs = NULL; vmc->vm_slot = childproc; region_init(&vmc->vm_regions_avl); vmc->vm_endpoint = NONE; /* In case someone tries to use it. */ diff --git a/servers/vm/mem_file.c b/servers/vm/mem_file.c index 3b7abbb70..93b546225 100644 --- a/servers/vm/mem_file.c +++ b/servers/vm/mem_file.c @@ -153,7 +153,7 @@ int mappedfile_copy(struct vir_region *vr, struct vir_region *newvr) mappedfile_setfile(newvr->parent, newvr, vr->param.file.fdref->fd, vr->param.file.offset, vr->param.file.fdref->dev, vr->param.file.fdref->ino, - vr->param.file.clearend, 0); + vr->param.file.clearend, 0, 0); assert(newvr->param.file.inited); return OK; @@ -161,10 +161,12 @@ int mappedfile_copy(struct vir_region *vr, struct vir_region *newvr) int mappedfile_setfile(struct vmproc *owner, struct vir_region *region, int fd, u64_t offset, - dev_t dev, ino_t ino, u16_t clearend, int prefill) + dev_t dev, ino_t ino, u16_t clearend, int prefill, int mayclosefd) { vir_bytes vaddr; - struct fdref *newref = fdref_dedup_or_new(owner, ino, dev, fd); + struct fdref *newref; + + newref = fdref_dedup_or_new(owner, ino, dev, fd, mayclosefd); assert(newref); assert(!region->param.file.inited); @@ -245,4 +247,5 @@ static void mappedfile_delete(struct vir_region *region) assert(region->param.file.inited); assert(region->param.file.fdref); fdref_deref(region); + region->param.file.inited = 0; } diff --git a/servers/vm/mmap.c b/servers/vm/mmap.c index c8b68a25a..3d2e6b5ec 100644 --- a/servers/vm/mmap.c +++ b/servers/vm/mmap.c @@ -84,7 +84,7 @@ static struct vir_region *mmap_region(struct vmproc *vmp, vir_bytes addr, static int mmap_file(struct vmproc *vmp, int vmfd, u32_t off_lo, u32_t off_hi, int flags, ino_t ino, dev_t dev, u64_t filesize, vir_bytes addr, vir_bytes len, - vir_bytes *retaddr, u16_t clearend, int writable) + vir_bytes *retaddr, u16_t clearend, int writable, int mayclosefd) { /* VFS has replied to a VMVFSREQ_FDLOOKUP request. */ struct vir_region *vr; @@ -136,7 +136,7 @@ static int mmap_file(struct vmproc *vmp, result = OK; mappedfile_setfile(vmp, vr, vmfd, - file_offset, dev, ino, clearend, 1); + file_offset, dev, ino, clearend, 1, mayclosefd); } return result; @@ -161,7 +161,7 @@ int do_vfs_mmap(message *m) m->m_u.m_vm_vfs.ino, m->m_u.m_vm_vfs.dev, (u64_t) LONG_MAX * VM_PAGE_SIZE, m->m_u.m_vm_vfs.vaddr, m->m_u.m_vm_vfs.len, &v, - clearend, flags); + clearend, flags, 0); } static void mmap_file_cont(struct vmproc *vmp, message *replymsg, void *cbarg, @@ -177,7 +177,7 @@ static void mmap_file_cont(struct vmproc *vmp, message *replymsg, void *cbarg, writable = 1; if(replymsg->VMV_RESULT != OK) { - printf("VM: VFS reply failed\n"); + printf("VM: VFS reply failed (%d)\n", replymsg->VMV_RESULT); sys_sysctl_stacktrace(vmp->vm_endpoint); result = origmsg->VMV_RESULT; } else { @@ -187,7 +187,7 @@ static void mmap_file_cont(struct vmproc *vmp, message *replymsg, void *cbarg, replymsg->VMV_INO, replymsg->VMV_DEV, (u64_t) replymsg->VMV_SIZE_PAGES*PAGE_SIZE, origmsg->VMM_ADDR, - origmsg->VMM_LEN, &v, 0, writable); + origmsg->VMM_LEN, &v, 0, writable, 1); } /* Unblock requesting process. */ diff --git a/servers/vm/proto.h b/servers/vm/proto.h index 9fd619293..f162045d2 100644 --- a/servers/vm/proto.h +++ b/servers/vm/proto.h @@ -230,10 +230,12 @@ int do_vfs_reply(message *m); /* mem_file.c */ int mappedfile_setfile(struct vmproc *owner, struct vir_region *region, int fd, u64_t offset, - dev_t dev, ino_t ino, u16_t clearend, int prefill); + dev_t dev, ino_t ino, u16_t clearend, int prefill, int mayclose); /* fdref.c */ struct fdref *fdref_new(struct vmproc *owner, ino_t ino, dev_t dev, int fd); -struct fdref *fdref_dedup_or_new(struct vmproc *owner, ino_t ino, dev_t dev, int fd); +struct fdref *fdref_dedup_or_new(struct vmproc *owner, ino_t ino, dev_t dev, + int fd, int mayclose); void fdref_ref(struct fdref *ref, struct vir_region *region); void fdref_deref(struct vir_region *region); +void fdref_sanitycheck(void); diff --git a/servers/vm/vmproc.h b/servers/vm/vmproc.h index bfa671cab..5e7145505 100644 --- a/servers/vm/vmproc.h +++ b/servers/vm/vmproc.h @@ -22,7 +22,6 @@ struct vmproc { vir_bytes vm_region_top; /* highest vaddr last inserted */ bitchunk_t vm_call_mask[VM_CALL_MASK_SIZE]; int vm_slot; /* process table slot */ - struct fdref *fdrefs; #if VMSTATS int vm_bytecopies; #endif @@ -32,6 +31,5 @@ struct vmproc { #define VMF_INUSE 0x001 /* slot contains a process */ #define VMF_EXITING 0x002 /* PM is cleaning up this process */ #define VMF_WATCHEXIT 0x008 /* Store in queryexit table */ -#define VMF_EXECING 0x010 /* exec() in progress */ #endif