pm, vfs, includes: mmap support
Change-Id: I831551e45a6781c74313c450eb9c967a68505932
This commit is contained in:
parent
e8681e9929
commit
8ca4e3a719
|
|
@ -734,6 +734,7 @@ struct
|
|||
{ "PROCCTL", VM_PROCCTL },
|
||||
{ "MAPCACHEPAGE", VM_MAPCACHEPAGE },
|
||||
{ "SETCACHEPAGE", VM_SETCACHEPAGE },
|
||||
{ "VFS_MMAP", VM_VFS_MMAP },
|
||||
{ NULL, 0 },
|
||||
};
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
*/
|
||||
|
|
|
|||
|
|
@ -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 *
|
||||
|
|
|
|||
|
|
@ -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.
|
||||
|
|
|
|||
|
|
@ -14,6 +14,8 @@ __weak_alias(vm_getphys, _vm_getphys)
|
|||
__weak_alias(vm_getrefcount, _vm_getrefcount)
|
||||
__weak_alias(minix_mmap, _minix_mmap)
|
||||
__weak_alias(minix_munmap, _minix_munmap)
|
||||
__weak_alias(mmap, _minix_mmap)
|
||||
__weak_alias(munmap, _minix_munmap)
|
||||
#endif
|
||||
|
||||
|
||||
|
|
@ -51,12 +53,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;
|
||||
|
|
|
|||
|
|
@ -6,6 +6,8 @@
|
|||
|
||||
#define _SYSTEM 1 /* get OK and negative error codes */
|
||||
|
||||
#include "../vfs/fdset.h"
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <limits.h>
|
||||
#include <errno.h>
|
||||
|
|
|
|||
|
|
@ -23,7 +23,7 @@ int do_get()
|
|||
*/
|
||||
|
||||
register struct mproc *rmp = mp;
|
||||
int r, i;
|
||||
int r;
|
||||
int ngroups;
|
||||
|
||||
switch(call_nr) {
|
||||
|
|
|
|||
|
|
@ -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];
|
||||
|
|
|
|||
|
|
@ -3,6 +3,8 @@
|
|||
|
||||
#define _SYSTEM 1
|
||||
|
||||
#include "vfs/fdset.h"
|
||||
|
||||
#include <minix/config.h>
|
||||
#include <limits.h>
|
||||
#include <errno.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 */
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
||||
/*===========================================================================*
|
||||
|
|
|
|||
|
|
@ -16,6 +16,7 @@
|
|||
|
||||
#include "fs.h"
|
||||
#include <sys/stat.h>
|
||||
#include <sys/mman.h>
|
||||
#include <minix/callnr.h>
|
||||
#include <minix/endpoint.h>
|
||||
#include <minix/com.h>
|
||||
|
|
@ -30,6 +31,7 @@
|
|||
#include "path.h"
|
||||
#include "param.h"
|
||||
#include "vnode.h"
|
||||
#include "file.h"
|
||||
#include <minix/vfsif.h>
|
||||
#include <machine/vmparam.h>
|
||||
#include <assert.h>
|
||||
|
|
@ -48,6 +50,8 @@ struct vfs_exec_info {
|
|||
int is_dyn; /* Dynamically linked executable */
|
||||
int elf_main_fd; /* Dyn: FD of main program execuatble */
|
||||
char execname[PATH_MAX]; /* Full executable invocation */
|
||||
int procfd;
|
||||
int procfd_used;
|
||||
};
|
||||
|
||||
static void lock_exec(void);
|
||||
|
|
@ -185,6 +189,27 @@ static int get_read_vp(struct vfs_exec_info *execi,
|
|||
r=get_read_vp(&e,f,p,s,rs,fp); if(r != OK) { FAILCHECK(r); } \
|
||||
} while(0)
|
||||
|
||||
static int vfs_memmap(struct exec_info *execi,
|
||||
vir_bytes vaddr, vir_bytes len, vir_bytes foffset, u16_t clearend,
|
||||
int protflags)
|
||||
{
|
||||
struct vfs_exec_info *vi = (struct vfs_exec_info *) execi->opaque;
|
||||
struct vnode *vp = ((struct vfs_exec_info *) execi->opaque)->vp;
|
||||
int r;
|
||||
u16_t flags = 0;
|
||||
|
||||
if(protflags & PROT_WRITE)
|
||||
flags |= MVM_WRITABLE;
|
||||
|
||||
r = minix_vfs_mmap(execi->proc_e, foffset, len,
|
||||
vp->v_dev, vp->v_inode_nr, vi->procfd, vaddr, clearend, flags);
|
||||
if(r == OK) {
|
||||
vi->procfd_used = 1;
|
||||
}
|
||||
|
||||
return r;
|
||||
}
|
||||
|
||||
/*===========================================================================*
|
||||
* pm_exec *
|
||||
*===========================================================================*/
|
||||
|
|
@ -205,14 +230,18 @@ int pm_exec(endpoint_t proc_e, vir_bytes path, size_t path_len,
|
|||
int i;
|
||||
static char fullpath[PATH_MAX],
|
||||
elf_interpreter[PATH_MAX],
|
||||
firstexec[PATH_MAX],
|
||||
finalexec[PATH_MAX];
|
||||
struct lookup resolve;
|
||||
stackhook_t makestack = NULL;
|
||||
static int n;
|
||||
n++;
|
||||
|
||||
lock_exec();
|
||||
|
||||
/* unset execi values are 0. */
|
||||
memset(&execi, 0, sizeof(execi));
|
||||
execi.procfd = -1;
|
||||
|
||||
/* passed from exec() libc code */
|
||||
execi.userflags = user_exec_flags;
|
||||
|
|
@ -223,6 +252,7 @@ int pm_exec(endpoint_t proc_e, vir_bytes path, size_t path_len,
|
|||
rfp = fp = &fproc[slot];
|
||||
|
||||
lookup_init(&resolve, fullpath, PATH_NOFLAGS, &execi.vmp, &execi.vp);
|
||||
|
||||
resolve.l_vmnt_lock = VMNT_READ;
|
||||
resolve.l_vnode_lock = VNODE_READ;
|
||||
|
||||
|
|
@ -244,6 +274,7 @@ int pm_exec(endpoint_t proc_e, vir_bytes path, size_t path_len,
|
|||
/* Get the exec file name. */
|
||||
FAILCHECK(fetch_name(path, path_len, fullpath));
|
||||
strlcpy(finalexec, fullpath, PATH_MAX);
|
||||
strlcpy(firstexec, fullpath, PATH_MAX);
|
||||
|
||||
/* Get_read_vp will return an opened vn in execi.
|
||||
* if necessary it releases the existing vp so we can
|
||||
|
|
@ -264,6 +295,7 @@ int pm_exec(endpoint_t proc_e, vir_bytes path, size_t path_len,
|
|||
FAILCHECK(fetch_name(path, path_len, fullpath));
|
||||
FAILCHECK(patch_stack(execi.vp, mbuf, &frame_len, fullpath));
|
||||
strlcpy(finalexec, fullpath, PATH_MAX);
|
||||
strlcpy(firstexec, fullpath, PATH_MAX);
|
||||
Get_read_vp(execi, fullpath, 1, 0, &resolve, fp);
|
||||
}
|
||||
|
||||
|
|
@ -280,7 +312,7 @@ int pm_exec(endpoint_t proc_e, vir_bytes path, size_t path_len,
|
|||
/* The interpreter (loader) needs an fd to the main program,
|
||||
* which is currently in finalexec
|
||||
*/
|
||||
if((r = execi.elf_main_fd = common_open(finalexec, O_RDONLY, 0)) < 0) {
|
||||
if((r = execi.elf_main_fd = common_open(finalexec, O_RDONLY, 0, 1)) < 0) {
|
||||
printf("VFS: exec: dynamic: open main exec failed %s (%d)\n",
|
||||
fullpath, r);
|
||||
FAILCHECK(r);
|
||||
|
|
@ -299,9 +331,25 @@ int pm_exec(endpoint_t proc_e, vir_bytes path, size_t path_len,
|
|||
* be looked up
|
||||
*/
|
||||
strlcpy(fullpath, elf_interpreter, PATH_MAX);
|
||||
strlcpy(firstexec, elf_interpreter, PATH_MAX);
|
||||
Get_read_vp(execi, fullpath, 0, 0, &resolve, fp);
|
||||
}
|
||||
|
||||
/* We also want an FD so VM can mmap() the process in if possible. */
|
||||
{
|
||||
int openr;
|
||||
if((openr=execi.procfd=common_open(firstexec, O_RDONLY, 0, 0)) < 0) {
|
||||
printf("vfs: exec: open failed of %s (%d), can't mmap\n",
|
||||
firstexec, openr);
|
||||
execi.procfd = -1;
|
||||
} else {
|
||||
if(fp->fp_filp[openr]->filp_vno->v_vmnt->m_haspeek &&
|
||||
major(fp->fp_filp[openr]->filp_vno->v_dev) != MEMORY_MAJOR) {
|
||||
execi.args.memmap = vfs_memmap;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
/* callback functions and data */
|
||||
execi.args.copymem = read_seg;
|
||||
execi.args.clearproc = libexec_clearproc_vm_procctl;
|
||||
|
|
@ -358,7 +406,13 @@ pm_execfinal:
|
|||
unlock_vnode(execi.vp);
|
||||
put_vnode(execi.vp);
|
||||
}
|
||||
if(execi.procfd >= 0 && !execi.procfd_used) {
|
||||
int r;
|
||||
r = close_fd(rfp, execi.procfd, 0);
|
||||
}
|
||||
|
||||
unlock_exec();
|
||||
|
||||
return(r);
|
||||
}
|
||||
|
||||
|
|
@ -649,9 +703,9 @@ static void clo_exec(struct fproc *rfp)
|
|||
int i;
|
||||
|
||||
/* Check the file desriptors one by one for presence of FD_CLOEXEC. */
|
||||
for (i = 0; i < OPEN_MAX; i++)
|
||||
for (i = 0; i < FDS_PER_PROCESS; i++)
|
||||
if ( FD_ISSET(i, &rfp->fp_cloexec_set))
|
||||
(void) close_fd(rfp, i);
|
||||
(void) close_fd(rfp, i, 0);
|
||||
}
|
||||
|
||||
/*===========================================================================*
|
||||
|
|
|
|||
11
servers/vfs/fdset.h
Normal file
11
servers/vfs/fdset.h
Normal file
|
|
@ -0,0 +1,11 @@
|
|||
#ifndef _FDSET_H
|
||||
#define _FDSET_H 1
|
||||
|
||||
#include "const.h"
|
||||
#ifdef FD_SETSIZE
|
||||
#error FD_SETSIZE already set
|
||||
#endif
|
||||
#define FD_SETSIZE FDS_PER_PROCESS
|
||||
#include <sys/fd_set.h>
|
||||
|
||||
#endif
|
||||
|
|
@ -15,12 +15,13 @@
|
|||
* the receiver.
|
||||
*/
|
||||
|
||||
#include "fs.h"
|
||||
|
||||
#include <sys/select.h>
|
||||
#include <minix/callnr.h>
|
||||
#include <minix/u64.h>
|
||||
#include <assert.h>
|
||||
#include <sys/stat.h>
|
||||
#include "fs.h"
|
||||
#include "file.h"
|
||||
#include "fproc.h"
|
||||
#include "vnode.h"
|
||||
|
|
@ -147,7 +148,8 @@ void init_filps(void)
|
|||
/*===========================================================================*
|
||||
* get_fd *
|
||||
*===========================================================================*/
|
||||
int get_fd(int start, mode_t bits, int *k, struct filp **fpt)
|
||||
int get_fd(struct fproc *rfp, int start, mode_t bits, int *k,
|
||||
struct filp **fpt, int userfd)
|
||||
{
|
||||
/* Look for a free file descriptor and a free filp slot. Fill in the mode word
|
||||
* in the latter, but don't claim either one yet, since the open() or creat()
|
||||
|
|
@ -156,10 +158,11 @@ int get_fd(int start, mode_t bits, int *k, struct filp **fpt)
|
|||
|
||||
register struct filp *f;
|
||||
register int i;
|
||||
int limit = userfd ? OPEN_MAX : FDS_PER_PROCESS;
|
||||
|
||||
/* Search the fproc fp_filp table for a free file descriptor. */
|
||||
for (i = start; i < OPEN_MAX; i++) {
|
||||
if (fp->fp_filp[i] == NULL && !FD_ISSET(i, &fp->fp_filp_inuse)) {
|
||||
for (i = start; i < limit; i++) {
|
||||
if (rfp->fp_filp[i] == NULL && !FD_ISSET(i, &rfp->fp_filp_inuse)) {
|
||||
/* A file descriptor has been located. */
|
||||
*k = i;
|
||||
break;
|
||||
|
|
@ -167,7 +170,7 @@ int get_fd(int start, mode_t bits, int *k, struct filp **fpt)
|
|||
}
|
||||
|
||||
/* Check to see if a file descriptor has been found. */
|
||||
if (i >= OPEN_MAX) return(EMFILE);
|
||||
if (i >= limit) return(EMFILE);
|
||||
|
||||
/* If we don't care about a filp, return now */
|
||||
if (fpt == NULL) return(OK);
|
||||
|
|
@ -203,32 +206,35 @@ int fild; /* file descriptor */
|
|||
tll_access_t locktype;
|
||||
{
|
||||
/* See if 'fild' refers to a valid file descr. If so, return its filp ptr. */
|
||||
|
||||
return get_filp2(fp, fild, locktype);
|
||||
return get_filp2(fp, fild, locktype, 1);
|
||||
}
|
||||
|
||||
|
||||
/*===========================================================================*
|
||||
* get_filp2 *
|
||||
*===========================================================================*/
|
||||
struct filp *get_filp2(rfp, fild, locktype)
|
||||
struct filp *get_filp2(rfp, fild, locktype, userrequest)
|
||||
register struct fproc *rfp;
|
||||
int fild; /* file descriptor */
|
||||
tll_access_t locktype;
|
||||
int userrequest;
|
||||
{
|
||||
/* See if 'fild' refers to a valid file descr. If so, return its filp ptr. */
|
||||
struct filp *filp;
|
||||
int fdlimit = userrequest ? OPEN_MAX : FDS_PER_PROCESS;
|
||||
|
||||
filp = NULL;
|
||||
if (fild < 0 || fild >= OPEN_MAX)
|
||||
if (fild < 0 || fild >= fdlimit) {
|
||||
err_code = EBADF;
|
||||
else if (rfp->fp_filp[fild] == NULL && FD_ISSET(fild, &rfp->fp_filp_inuse))
|
||||
} else if (rfp->fp_filp[fild] == NULL && FD_ISSET(fild, &rfp->fp_filp_inuse))
|
||||
err_code = EIO; /* The filedes is not there, but is not closed either.
|
||||
*/
|
||||
else if ((filp = rfp->fp_filp[fild]) == NULL)
|
||||
else if ((filp = rfp->fp_filp[fild]) == NULL) {
|
||||
err_code = EBADF;
|
||||
else
|
||||
} else {
|
||||
assert(filp->filp_count > 0);
|
||||
lock_filp(filp, locktype); /* All is fine */
|
||||
}
|
||||
|
||||
return(filp); /* may also be NULL */
|
||||
}
|
||||
|
|
@ -269,7 +275,7 @@ int invalidate_filp(struct filp *rfilp)
|
|||
int f, fd, n = 0;
|
||||
for (f = 0; f < NR_PROCS; f++) {
|
||||
if (fproc[f].fp_pid == PID_FREE) continue;
|
||||
for (fd = 0; fd < OPEN_MAX; fd++) {
|
||||
for (fd = 0; fd < FDS_PER_PROCESS; fd++) {
|
||||
if(fproc[f].fp_filp[fd] && fproc[f].fp_filp[fd] == rfilp) {
|
||||
fproc[f].fp_filp[fd] = NULL;
|
||||
n++;
|
||||
|
|
@ -435,7 +441,7 @@ int fd;
|
|||
if (isokendpt(ep, &slot) != OK)
|
||||
return(NULL);
|
||||
|
||||
rfilp = get_filp2(&fproc[slot], fd, VNODE_READ);
|
||||
rfilp = get_filp2(&fproc[slot], fd, VNODE_READ, 1);
|
||||
|
||||
return(rfilp);
|
||||
}
|
||||
|
|
@ -498,7 +504,7 @@ filp_id_t cfilp;
|
|||
rfp = &fproc[slot];
|
||||
|
||||
/* Find an open slot in fp_filp */
|
||||
for (fd = 0; fd < OPEN_MAX; fd++) {
|
||||
for (fd = 0; fd < FDS_PER_PROCESS; fd++) {
|
||||
if (rfp->fp_filp[fd] == NULL &&
|
||||
!FD_ISSET(fd, &rfp->fp_filp_inuse)) {
|
||||
|
||||
|
|
|
|||
|
|
@ -2,6 +2,7 @@
|
|||
#define __VFS_FPROC_H__
|
||||
|
||||
#include "threads.h"
|
||||
#include "fdset.h"
|
||||
|
||||
#include <sys/select.h>
|
||||
#include <minix/safecopies.h>
|
||||
|
|
@ -20,7 +21,7 @@ EXTERN struct fproc {
|
|||
struct vnode *fp_wd; /* working directory; NULL during reboot */
|
||||
struct vnode *fp_rd; /* root directory; NULL during reboot */
|
||||
|
||||
struct filp *fp_filp[OPEN_MAX];/* the file descriptor table */
|
||||
struct filp *fp_filp[FDS_PER_PROCESS]; /* the file descriptor table */
|
||||
fd_set fp_filp_inuse; /* which fd's are in use? */
|
||||
fd_set fp_cloexec_set; /* bit map for POSIX Table 6-2 FD_CLOEXEC */
|
||||
|
||||
|
|
|
|||
|
|
@ -6,8 +6,12 @@
|
|||
*/
|
||||
#define _SYSTEM 1 /* tell headers that this is the kernel */
|
||||
|
||||
/* Get the right-sized fd_set */
|
||||
#include "fdset.h"
|
||||
|
||||
/* The following are so basic, all the *.c files get them automatically. */
|
||||
#include <minix/config.h> /* MUST be first */
|
||||
#include <minix/config.h>
|
||||
|
||||
#include <sys/types.h>
|
||||
#include <minix/const.h>
|
||||
#include <minix/type.h>
|
||||
|
|
@ -23,7 +27,6 @@
|
|||
#include <minix/sysutil.h>
|
||||
#include <minix/timers.h>
|
||||
|
||||
#include "const.h"
|
||||
#include "dmap.h"
|
||||
#include "proto.h"
|
||||
#include "threads.h"
|
||||
|
|
|
|||
|
|
@ -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' */
|
||||
|
||||
|
|
|
|||
|
|
@ -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,145 @@ 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 {
|
||||
f->filp_vno->v_mmapped = 1;
|
||||
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;
|
||||
|
||||
#if 0
|
||||
printf("VFS: FDLOOKUP: result %d dev 0x%x ino %ld; procfd %d for %d\n",
|
||||
result, m_out->VMV_DEV, m_out->VMV_INO, procfd, rfp->fp_endpoint);
|
||||
#endif
|
||||
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 +536,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 +580,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 +617,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 +824,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,20 +837,25 @@ 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 */
|
||||
#if 0
|
||||
r = sys_datacopy(PM_PROC_NR, exe_name, VFS_PROC_NR, (vir_bytes) proc_name,
|
||||
PROC_NAME_LEN);
|
||||
if (r != OK) goto core_exit;
|
||||
#else
|
||||
exe_name = 0;
|
||||
strcpy(proc_name, "coreprog");
|
||||
#endif
|
||||
proc_name[PROC_NAME_LEN - 1] = '\0';
|
||||
|
||||
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 +914,4 @@ void panic_hook(void)
|
|||
printf("VFS mthread stacktraces:\n");
|
||||
mthread_stacktraces();
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
|
||||
|
|
@ -136,22 +148,31 @@ int read_write(int rw_flag, struct filp *f, char *buf, size_t size,
|
|||
|
||||
assert(rw_flag == READING || rw_flag == WRITING || rw_flag == PEEKING);
|
||||
|
||||
if (size > SSIZE_MAX) return(EINVAL);
|
||||
if (size > SSIZE_MAX) {
|
||||
printf("read_write: size too big, %zu\n", size);
|
||||
return(EINVAL);
|
||||
}
|
||||
|
||||
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 +191,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 +212,25 @@ 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);
|
||||
#if 0
|
||||
printf("vfs: req_peek ino %d position 0x%llx len 0x%x returns %d\n",
|
||||
vp->v_inode_nr, position, size, r);
|
||||
#endif
|
||||
} 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 +252,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 +324,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;
|
||||
|
||||
|
|
|
|||
|
|
@ -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. */
|
||||
|
|
|
|||
|
|
@ -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];
|
||||
|
|
|
|||
|
|
@ -23,6 +23,7 @@ EXTERN struct vnode {
|
|||
dev_t v_sdev; /* device number for special files */
|
||||
struct vmnt *v_vmnt; /* vmnt object of the partition */
|
||||
tll_t v_lock; /* three-level-lock */
|
||||
int v_mmapped; /* inuse for mmap -> inform vm of shrinkage */
|
||||
} vnode[NR_VNODES];
|
||||
|
||||
/* vnode lock types mapping */
|
||||
|
|
|
|||
|
|
@ -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 || \
|
||||
|
|
|
|||
|
|
@ -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)
|
||||
|
|
|
|||
Loading…
Reference in New Issue
Block a user