CPPFLAGS+= -DUSE_COVERAGE
.endif
+CFLAGS+= -Wall -Wextra
DPADD+= ${LIBSYS} ${LIBTIMERS} ${LIBEXEC}
LDADD+= -lsys -ltimers -lexec -lmthread
*/
int r, transid;
- if (vmp->m_fs_e == rfp->fp_endpoint) return(EDEADLK);
vmp->m_comm.c_cur_reqs++; /* One more request awaiting a reply */
-
transid = rfp->fp_wtid + VFS_TRANSID;
rfp->fp_sendrec->m_type = TRNS_ADD_ID(rfp->fp_sendrec->m_type, transid);
rfp->fp_task = vmp->m_fs_e;
* synchronous character driver */
endpt = st.REP_ENDPT;
if (endpt == VFS_PROC_NR) {
- endpt = find_suspended_ep(m->m_source,st.REP_IO_GRANT);
- if(endpt == NONE) {
+ endpt = find_suspended_ep(m->m_source, st.REP_IO_GRANT);
+ if (endpt == NONE) {
printf("VFS: proc with grant %d from %d not found\n",
st.REP_IO_GRANT, st.m_source);
continue;
case VFS_DEV_IOCTL:
*pos_lo = *io_ept; /* Old endpoint in POSITION field. */
*op = DEV_IOCTL_S;
- if(_MINIX_IOCTL_IOR(m_in.REQUEST)) access |= CPF_WRITE;
- if(_MINIX_IOCTL_IOW(m_in.REQUEST)) access |= CPF_READ;
- if(_MINIX_IOCTL_BIG(m_in.REQUEST))
- size = _MINIX_IOCTL_SIZE_BIG(m_in.REQUEST);
+ /* For IOCTLs, the bytes parameter encodes requested access method
+ * and buffer size */
+ if(_MINIX_IOCTL_IOR(bytes)) access |= CPF_WRITE;
+ if(_MINIX_IOCTL_IOW(bytes)) access |= CPF_READ;
+ if(_MINIX_IOCTL_BIG(bytes))
+ size = _MINIX_IOCTL_SIZE_BIG(bytes);
else
- size = _MINIX_IOCTL_SIZE(m_in.REQUEST);
+ size = _MINIX_IOCTL_SIZE(bytes);
/* Grant access to the buffer even if no I/O happens with the ioctl, in
* order to disambiguate requests with DEV_IOCTL_S.
if (ret == SUSPEND) {
if ((flags & O_NONBLOCK) && !is_asyn) {
/* Not supposed to block. */
- ret = cancel_nblock(dp, minor_dev, call_nr, ioproc, gid);
+ ret = cancel_nblock(dp, minor_dev, job_call_nr, ioproc, gid);
if (ret == EINTR)
ret = EAGAIN;
} else {
if ((flags & O_NONBLOCK) && !is_asyn) {
/* Not supposed to block, send cancel message */
- cancel_nblock(dp, minor_dev, call_nr, ioproc, gid);
+ cancel_nblock(dp, minor_dev, job_call_nr, ioproc, gid);
/*
* FIXME Should do something about EINTR -> EAGAIN
* mapping
/*===========================================================================*
* pm_setsid *
*===========================================================================*/
-void pm_setsid(proc_e)
-int proc_e;
+void pm_setsid(endpoint_t proc_e)
{
/* Perform the VFS side of the SETSID call, i.e. get rid of the controlling
* terminal of a process, and make the process a session leader.
*===========================================================================*/
int do_ioctl()
{
-/* Perform the ioctl(ls_fd, request, argx) system call (uses m2 fmt). */
+/* Perform the ioctl(ls_fd, request, argx) system call */
- int r = OK, suspend_reopen;
+ int r = OK, suspend_reopen, ioctlrequest;
struct filp *f;
register struct vnode *vp;
dev_t dev;
+ void *argx;
- scratch(fp).file.fd_nr = m_in.ls_fd;
+ scratch(fp).file.fd_nr = job_m_in.ls_fd;
+ ioctlrequest = job_m_in.REQUEST;
+ argx = job_m_in.ADDRESS;
if ((f = get_filp(scratch(fp).file.fd_nr, VNODE_READ)) == NULL)
return(err_code);
dev = (dev_t) vp->v_sdev;
if ((vp->v_mode & I_TYPE) == I_BLOCK_SPECIAL)
- r = bdev_ioctl(dev, who_e, m_in.REQUEST, m_in.ADDRESS);
+ r = bdev_ioctl(dev, who_e, ioctlrequest, argx);
else
- r = dev_io(VFS_DEV_IOCTL, dev, who_e, m_in.ADDRESS, cvu64(0),
- m_in.REQUEST, f->filp_flags, suspend_reopen);
+ r = dev_io(VFS_DEV_IOCTL, dev, who_e, argx, cvu64(0),
+ ioctlrequest, f->filp_flags, suspend_reopen);
}
unlock_filp(f);
endpoint_t proc_e;
int slot;
- proc_e = m_in.REP_ENDPT;
+ proc_e = job_m_in.REP_ENDPT;
if (isokendpt(proc_e, &slot) != OK) return;
rfp = &fproc[slot];
- *rfp->fp_sendrec = m_in;
- worker_signal(worker_get(rfp->fp_wtid)); /* Continue open */
+ *rfp->fp_sendrec = job_m_in;
+ if (rfp->fp_wtid != invalid_thread_id)
+ worker_signal(worker_get(rfp->fp_wtid)); /* Continue open */
}
/*===========================================================================*
struct vnode *vp;
struct dmap *dp;
- driver_e = m_in.m_source;
- filp_no = m_in.REP_ENDPT;
- status = m_in.REP_STATUS;
+ driver_e = job_m_in.m_source;
+ filp_no = job_m_in.REP_ENDPT;
+ status = job_m_in.REP_STATUS;
if (filp_no < 0 || filp_no >= NR_FILPS) {
printf("VFS: reopen_reply: bad filp number %d from driver %d\n",
* etc), and its label. This label is registered with DS, and allows us to
* retrieve the driver's endpoint.
*/
- int r, flags, major;
+ int r, flags, major, style;
endpoint_t endpoint;
vir_bytes label_vir;
size_t label_len;
/* Only RS can map drivers. */
if (who_e != RS_PROC_NR) return(EPERM);
- /* Get the label */
- label_vir = (vir_bytes) m_in.md_label;
- label_len = (size_t) m_in.md_label_len;
+ label_vir = (vir_bytes) job_m_in.md_label;
+ label_len = (size_t) job_m_in.md_label_len;
+ major = job_m_in.md_major;
+ flags = job_m_in.md_flags;
+ style = job_m_in.md_style;
+ /* Get the label */
if (label_len+1 > sizeof(label)) { /* Can we store this label? */
printf("VFS: do_mapdriver: label too long\n");
return(EINVAL);
}
/* Try to update device mapping. */
- major = m_in.md_major;
- flags = m_in.md_flags;
-
- return map_driver(label, major, endpoint, m_in.md_style, flags);
+ return map_driver(label, major, endpoint, style, flags);
}
/*===========================================================================*
static void lock_exec(void);
static void unlock_exec(void);
-static int exec_newmem(int proc_e, vir_bytes text_addr, vir_bytes
- text_bytes, vir_bytes data_addr, vir_bytes data_bytes, vir_bytes
- tot_bytes, vir_bytes frame_len, int sep_id, int is_elf, dev_t st_dev,
+static int exec_newmem(int proc_e, vir_bytes text_addr, vir_bytes text_bytes,
+ vir_bytes data_addr, vir_bytes data_bytes, vir_bytes tot_bytes,
+ vir_bytes frame_len, int sep_id, int is_elf, dev_t st_dev,
ino_t st_ino, time_t ctime, char *progname, int new_uid, int new_gid,
vir_bytes *stack_topp, int *load_textp, int *setugidp);
static int is_script(const char *exec_hdr, size_t exec_len);
-static int patch_stack(struct vnode *vp, char stack[ARG_MAX], vir_bytes
- *stk_bytes, char path[PATH_MAX]);
-static int insert_arg(char stack[ARG_MAX], vir_bytes *stk_bytes, char
- *arg, int replace);
+static int patch_stack(struct vnode *vp, char stack[ARG_MAX],
+ size_t *stk_bytes, char path[PATH_MAX]);
+static int insert_arg(char stack[ARG_MAX], size_t *stk_bytes, char *arg,
+ int replace);
static void patch_ptr(char stack[ARG_MAX], vir_bytes base);
static void clo_exec(struct fproc *rfp);
static int read_seg(struct vnode *vp, off_t off, int proc_e, int seg,
*===========================================================================*/
static void lock_exec(void)
{
- message org_m_in;
struct fproc *org_fp;
struct worker_thread *org_self;
if (mutex_trylock(&exec_lock) == 0)
return;
- org_m_in = m_in;
org_fp = fp;
org_self = self;
if (mutex_lock(&exec_lock) != 0)
panic("Could not obtain lock on exec");
- m_in = org_m_in;
fp = org_fp;
self = org_self;
}
/*===========================================================================*
* pm_exec *
*===========================================================================*/
-int pm_exec(int proc_e, char *path, vir_bytes path_len, char *frame,
- vir_bytes frame_len, vir_bytes *pc)
+int pm_exec(endpoint_t proc_e, vir_bytes path, size_t path_len,
+ vir_bytes frame, size_t frame_len, vir_bytes *pc)
{
/* Perform the execve(name, argv, envp) call. The user library builds a
* complete stack image, including pointers, args, environ, etc. The stack
resolve.l_vnode_lock = VNODE_READ;
/* Get the exec file name. */
- if ((r = fetch_name(path, path_len, 0, fullpath)) != OK)
+ if ((r = fetch_name(path, path_len, fullpath)) != OK)
goto pm_execfinal;
/* Fetch the stack from the user before destroying the old core image. */
goto pm_execfinal;
}
r = sys_datacopy(proc_e, (vir_bytes) frame, SELF, (vir_bytes) mbuf,
- (phys_bytes) frame_len);
+ (size_t) frame_len);
if (r != OK) { /* can't fetch stack (e.g. bad virtual addr) */
printf("VFS: pm_exec: sys_datacopy failed\n");
goto pm_execfinal;
r = r1;
else
r = req_stat(vp->v_fs_e, vp->v_inode_nr, VFS_PROC_NR,
- (char *) &(execi.sb), 0, 0);
+ (vir_bytes) &(execi.sb), 0, 0);
if (r != OK) goto pm_execfinal;
if (round == 0) {
break;
/* Get fresh copy of the file name. */
- if ((r = fetch_name(path, path_len, 0, fullpath)) != OK)
+ if ((r = fetch_name(path, path_len, fullpath)) != OK)
printf("VFS pm_exec: 2nd fetch_name failed\n");
else
r = patch_stack(vp, mbuf, &frame_len, fullpath);
r = exec_newmem(proc_e, 0 /* text_addr */, text_bytes,
0 /* data_addr */, data_bytes + bss_bytes, tot_bytes,
- execi->frame_len, sep_id, 0 /* is_elf */, vp->v_dev, vp->v_inode_nr,
- execi->sb.st_ctime,
- execi->progname, execi->new_uid, execi->new_gid,
+ execi->frame_len, sep_id, 0 /* is_elf */, vp->v_dev,
+ vp->v_inode_nr, execi->sb.st_ctime, execi->progname,
+ execi->new_uid, execi->new_gid,
&execi->stack_top, &execi->load_text, &execi->setugid);
if (r != OK) {
static int patch_stack(vp, stack, stk_bytes, path)
struct vnode *vp; /* pointer for open script file */
char stack[ARG_MAX]; /* pointer to stack image within VFS */
-vir_bytes *stk_bytes; /* size of initial stack */
+size_t *stk_bytes; /* size of initial stack */
char path[PATH_MAX]; /* path to script file */
{
/* Patch the argument vector to include the path name of the script to be
*===========================================================================*/
static int insert_arg(
char stack[ARG_MAX], /* pointer to stack image within PM */
-vir_bytes *stk_bytes, /* size of initial stack */
+size_t *stk_bytes, /* size of initial stack */
char *arg, /* argument to prepend/replace as new argv[0] */
int replace
)
* pointers are really offsets from the start of stack.
* Return true iff the operation succeeded.
*/
- int offset, a0, a1, old_bytes = *stk_bytes;
+ int offset, a0, a1;
+ size_t old_bytes = *stk_bytes;
/* Prepending arg adds at least one string and a zero byte. */
offset = strlen(arg) + 1;
}
if (r == OK && cum_io != seg_bytes)
- printf("VFS: read_seg segment has not been read properly by exec()\n");
+ printf("VFS: read_seg segment has not been read properly\n");
return(r);
}
r = mutex_trylock(&f->filp_lock);
if (r == -EDEADLK)
panic("Thread %d still holds filp lock on filp %p call_nr=%d\n",
- mthread_self(), f, call_nr);
+ mthread_self(), f, job_call_nr);
else if (r == 0) {
/* We just obtained the lock, release it */
mutex_unlock(&f->filp_lock);
struct filp *filp;
tll_access_t locktype;
{
- message org_m_in;
struct fproc *org_fp;
struct worker_thread *org_self;
struct vnode *vp;
if (mutex_trylock(&filp->filp_lock) != 0) {
/* Already in use, let's wait for our turn */
- org_m_in = m_in;
org_fp = fp;
org_self = self;
if (mutex_lock(&filp->filp_lock) != 0)
panic("unable to obtain lock on filp");
- m_in = org_m_in;
fp = org_fp;
self = org_self;
}
int do_verify_fd(void)
{
struct filp *rfilp;
- rfilp = (struct filp *) verify_fd(m_in.USER_ENDPT, m_in.COUNT);
+ endpoint_t proc_e;
+ int fd;
+
+ proc_e = job_m_in.USER_ENDPT;
+ fd = job_m_in.COUNT;
+
+ rfilp = (struct filp *) verify_fd(proc_e, fd);
m_out.ADDRESS = (void *) rfilp;
if (rfilp != NULL) unlock_filp(rfilp);
return (rfilp != NULL) ? OK : EINVAL;
*===========================================================================*/
int do_set_filp(void)
{
- return set_filp((filp_id_t) m_in.ADDRESS);
+ filp_id_t f;
+ f = (filp_id_t) job_m_in.ADDRESS;
+ return set_filp(f);
}
/*===========================================================================*
*===========================================================================*/
int do_copy_filp(void)
{
- return copy_filp(m_in.USER_ENDPT, (filp_id_t) m_in.ADDRESS);
+ endpoint_t proc_e;
+ filp_id_t f;
+
+ proc_e = job_m_in.USER_ENDPT;
+ f = (filp_id_t) job_m_in.ADDRESS;
+
+ return copy_filp(proc_e, f);
}
/*===========================================================================*
*===========================================================================*/
int do_put_filp(void)
{
- return put_filp((filp_id_t) m_in.ADDRESS);
+ filp_id_t f;
+ f = (filp_id_t) job_m_in.ADDRESS;
+ return put_filp(f);
}
/*===========================================================================*
*===========================================================================*/
int do_cancel_fd(void)
{
- return cancel_fd(m_in.USER_ENDPT, m_in.COUNT);
+ endpoint_t proc_e;
+ int fd;
+
+ proc_e = job_m_in.USER_ENDPT;
+ fd = job_m_in.COUNT;
+
+ return cancel_fd(proc_e, fd);
}
/*===========================================================================*
#define _MINIX 1 /* tell headers to include MINIX stuff */
#define _SYSTEM 1 /* tell headers that this is the kernel */
-#define DO_SANITYCHECKS 0
-
-#if DO_SANITYCHECKS
-#define SANITYCHECK do { \
- if(!check_vrefs() || !check_pipe()) { \
- printf("VFS:%s:%d: call_nr %d who_e %d\n", \
- __FILE__, __LINE__, call_nr, who_e); \
- panic("sanity check failed"); \
- } \
-} while(0)
-#else
-#define SANITYCHECK
-#endif
-
/* The following are so basic, all the *.c files get them automatically. */
#include <minix/config.h> /* MUST be first */
#include <sys/types.h>
return(EPERM);
globals[depth].g_fp = fp;
- globals[depth].g_m_in = m_in;
+ globals[depth].g_m_in = job_m_in;
globals[depth].g_m_out = m_out;
globals[depth].g_super_user = super_user;
depth--;
fp = globals[depth].g_fp;
- m_in = globals[depth].g_m_in;
+ job_m_in = globals[depth].g_m_in;
m_out = globals[depth].g_m_out;
}
set_globals(m);
/* Perform the nested call - only getsysinfo() is allowed right now */
- if (call_nr == COMMON_GETSYSINFO) {
+ if (job_call_nr == COMMON_GETSYSINFO) {
r = do_getsysinfo();
} else {
- printf("VFS: invalid nested call %d from FS %d\n", call_nr,
+ printf("VFS: invalid nested call %d from FS %d\n", job_call_nr,
who_e);
r = ENOSYS;
int r, n;
pid_t target;
message m;
+ vir_bytes buf;
- size = m_in.GCOV_BUFF_SZ;
- target = m_in.GCOV_PID;
+ size = job_m_in.GCOV_BUFF_SZ;
+ target = job_m_in.GCOV_PID;
+ buf = (vir_bytes) job_m_in.GCOV_BUFF_P;
/* If the wrong process is sent to, the system hangs; so make this root-only.
*/
rfp = &fproc[n];
/* Grant target process to requestor's buffer. */
- if ((grantid = cpf_grant_magic(rfp->fp_endpoint, who_e,
- (vir_bytes) m_in.GCOV_BUFF_P, size,
- CPF_WRITE)) < 0) {
+ if ((grantid = cpf_grant_magic(rfp->fp_endpoint, who_e, buf,
+ size, CPF_WRITE)) < 0) {
printf("VFS: gcov_flush: grant failed\n");
return(ENOMEM);
}
- if(rfp->fp_endpoint == VFS_PROC_NR) {
+ if (rfp->fp_endpoint == VFS_PROC_NR) {
/* Request is for VFS itself. */
r = gcov_flush(grantid, size);
} else {
# define who_p ((int) (fp - fproc))
# define isokslot(p) (p >= 0 && \
p < (int)(sizeof(fproc) / sizeof(struct fproc)))
-#if 0
-# define who_e (isokslot(who_p) ? fp->fp_endpoint : m_in.m_source)
-#else
-# define who_e (isokslot(who_p) && fp->fp_endpoint != NONE ? \
- fp->fp_endpoint : m_in.m_source)
-#endif
+# define who_e (self != NULL && fp != NULL ? fp->fp_endpoint : \
+ m_in.m_source)
# define call_nr (m_in.m_type)
+# define job_m_in (self->w_job.j_m_in)
+# define job_call_nr (job_m_in.m_type)
# define super_user (fp->fp_effuid == SU_UID ? 1 : 0)
# define scratch(p) (scratchpad[((int) ((p) - fproc))])
EXTERN struct worker_thread *self;
EXTERN struct worker_thread workers[NR_WTHREADS];
EXTERN struct worker_thread sys_worker;
EXTERN struct worker_thread dl_worker;
+EXTERN thread_t invalid_thread_id;
EXTERN char mount_label[LABEL_MAX]; /* label of file system to mount */
/* The following variables are used for returning results to the caller. */
#include "path.h"
#include "vnode.h"
#include "param.h"
+#include "scratchpad.h"
/*===========================================================================*
* do_link *
struct vmnt *vmp1 = NULL, *vmp2 = NULL;
char fullpath[PATH_MAX];
struct lookup resolve;
+ vir_bytes vname1, vname2;
+ size_t vname1_length, vname2_length;
+
+ vname1 = (vir_bytes) job_m_in.name1;
+ vname1_length = job_m_in.name1_length;
+ vname2 = (vir_bytes) job_m_in.name2;
+ vname2_length = job_m_in.name2_length;
lookup_init(&resolve, fullpath, PATH_NOFLAGS, &vmp1, &vp);
resolve.l_vmnt_lock = VMNT_WRITE;
resolve.l_vnode_lock = VNODE_READ;
/* See if 'name1' (file to be linked to) exists. */
- if (fetch_name(m_in.name1, m_in.name1_length, M1, fullpath) != OK)
- return(err_code);
+ if (fetch_name(vname1, vname1_length, fullpath) != OK) return(err_code);
if ((vp = eat_path(&resolve, fp)) == NULL) return(err_code);
/* Does the final directory of 'name2' exist? */
lookup_init(&resolve, fullpath, PATH_NOFLAGS, &vmp2, &dirp);
resolve.l_vmnt_lock = VMNT_READ;
resolve.l_vnode_lock = VNODE_READ;
- if (fetch_name(m_in.name2, m_in.name2_length, M1, fullpath) != OK)
+ if (fetch_name(vname2, vname2_length, fullpath) != OK)
r = err_code;
else if ((dirp = last_dir(&resolve, fp)) == NULL)
r = err_code;
return(r);
}
-
/*===========================================================================*
* do_unlink *
*===========================================================================*/
/* Perform the unlink(name) or rmdir(name) system call. The code for these two
* is almost the same. They differ only in some condition testing. Unlink()
* may be used by the superuser to do dangerous things; rmdir() may not.
+ * The syscall might provide 'name' embedded in the message.
*/
struct vnode *dirp, *vp;
struct vmnt *vmp, *vmp2;
int r;
char fullpath[PATH_MAX];
struct lookup resolve;
+ vir_bytes vname;
+ size_t vname_length;
+
+ vname = (vir_bytes) job_m_in.name;
+ vname_length = job_m_in.name_length;
+ if (copy_name(vname_length, fullpath) != OK) {
+ /* Direct copy failed, try fetching from user space */
+ if (fetch_name(vname, vname_length, fullpath) != OK)
+ return(err_code);
+ }
lookup_init(&resolve, fullpath, PATH_RET_SYMLINK, &vmp, &dirp);
resolve.l_vmnt_lock = VMNT_WRITE;
resolve.l_vnode_lock = VNODE_READ;
/* Get the last directory in the path. */
- if (fetch_name(m_in.name, m_in.name_length, M3, fullpath) != OK)
- return(err_code);
-
if ((dirp = last_dir(&resolve, fp)) == NULL) return(err_code);
- assert(vmp != NULL);
+ assert(vmp != NULL); /* We must have locked the vmnt */
/* Make sure that the object is a directory */
if ((dirp->v_mode & I_TYPE) != I_DIRECTORY) {
assert(vmp != NULL);
tll_upgrade(&vmp->m_lock);
- if (call_nr == UNLINK)
+ if (job_call_nr == UNLINK)
r = req_unlink(dirp->v_fs_e, dirp->v_inode_nr, fullpath);
else
r = req_rmdir(dirp->v_fs_e, dirp->v_inode_nr, fullpath);
char old_name[PATH_MAX];
char fullpath[PATH_MAX];
struct lookup resolve;
+ vir_bytes vname1, vname2;
+ size_t vname1_length, vname2_length;
+
+ vname1 = (vir_bytes) job_m_in.name1;
+ vname1_length = job_m_in.name1_length;
+ vname2 = (vir_bytes) job_m_in.name2;
+ vname2_length = job_m_in.name2_length;
lookup_init(&resolve, fullpath, PATH_NOFLAGS, &oldvmp, &old_dirp);
/* Do not yet request exclusive lock on vmnt to prevent deadlocks later on */
resolve.l_vnode_lock = VNODE_READ;
/* See if 'name1' (existing file) exists. Get dir and file inodes. */
- if (fetch_name(m_in.name1, m_in.name1_length, M1, fullpath) != OK)
- return(err_code);
- if ((old_dirp = last_dir(&resolve, fp)) == NULL)
- return(err_code);
+ if (fetch_name(vname1, vname1_length, fullpath) != OK) return(err_code);
+ if ((old_dirp = last_dir(&resolve, fp)) == NULL) return(err_code);
/* If the sticky bit is set, only the owner of the file or a privileged
user is allowed to rename */
}
/* Save the last component of the old name */
- if(strlen(fullpath) >= sizeof(old_name)) {
+ if (strlen(fullpath) >= sizeof(old_name)) {
unlock_vnode(old_dirp);
unlock_vmnt(oldvmp);
put_vnode(old_dirp);
lookup_init(&resolve, fullpath, PATH_NOFLAGS, &newvmp, &new_dirp);
resolve.l_vmnt_lock = VMNT_READ;
resolve.l_vnode_lock = VNODE_READ;
- if (fetch_name(m_in.name2, m_in.name2_length, M1, fullpath) != OK)
- r = err_code;
- else if ((new_dirp = last_dir(&resolve, fp)) == NULL)
- r = err_code;
+ if (fetch_name(vname2, vname2_length, fullpath) != OK) r = err_code;
+ else if ((new_dirp = last_dir(&resolve, fp)) == NULL) r = err_code;
if (r != OK) {
unlock_vnode(old_dirp);
int r;
char fullpath[PATH_MAX];
struct lookup resolve;
+ off_t length;
+ vir_bytes vname;
+ size_t vname_length;
+
+ vname = (vir_bytes) job_m_in.m2_p1;
+ vname_length = job_m_in.m2_i1;
lookup_init(&resolve, fullpath, PATH_NOFLAGS, &vmp, &vp);
resolve.l_vmnt_lock = VMNT_EXCL;
resolve.l_vnode_lock = VNODE_WRITE;
- if ((off_t) m_in.flength < 0) return(EINVAL);
+ length = (off_t) job_m_in.flength;
+ if (length < 0) return(EINVAL);
/* Temporarily open file */
- if (fetch_name(m_in.m2_p1, m_in.m2_i1, M1, fullpath) != OK) return(err_code);
+ if (fetch_name(vname, vname_length, fullpath) != OK) return(err_code);
if ((vp = eat_path(&resolve, fp)) == NULL) return(err_code);
/* Ask FS to truncate the file */
if ((r = forbidden(fp, vp, W_BIT)) == OK)
- r = truncate_vnode(vp, m_in.flength);
+ r = truncate_vnode(vp, length);
unlock_vnode(vp);
unlock_vmnt(vmp);
/* As with do_truncate(), truncate_vnode() does the actual work. */
struct filp *rfilp;
int r;
+ off_t length;
+
+ scratch(fp).file.fd_nr = job_m_in.fd;
+ length = (off_t) job_m_in.flength;
- if ((off_t) m_in.flength < 0) return(EINVAL);
+ if (length < 0) return(EINVAL);
/* File is already opened; get a vnode pointer from filp */
- if ((rfilp = get_filp(m_in.m2_i1, VNODE_WRITE)) == NULL) return(err_code);
+ if ((rfilp = get_filp(scratch(fp).file.fd_nr, VNODE_WRITE)) == NULL)
+ return(err_code);
if (!(rfilp->filp_mode & W_BIT))
r = EBADF;
else
- r = truncate_vnode(rfilp->filp_vno, m_in.flength);
+ r = truncate_vnode(rfilp->filp_vno, length);
unlock_filp(rfilp);
return(r);
struct vmnt *vmp;
char fullpath[PATH_MAX];
struct lookup resolve;
+ vir_bytes vname1, vname2;
+ size_t vname1_length, vname2_length;
lookup_init(&resolve, fullpath, PATH_NOFLAGS, &vmp, &vp);
resolve.l_vmnt_lock = VMNT_WRITE;
resolve.l_vnode_lock = VNODE_READ;
- if (m_in.name1_length <= 1) return(ENOENT);
- if (m_in.name1_length >= SYMLINK_MAX) return(ENAMETOOLONG);
+ vname1 = (vir_bytes) job_m_in.name1;
+ vname1_length = job_m_in.name1_length;
+ vname2 = (vir_bytes) job_m_in.name2;
+ vname2_length = job_m_in.name2_length;
- /* Get dir inode of 'name2' */
- if (fetch_name(m_in.name2, m_in.name2_length, M1, fullpath) != OK)
- return(err_code);
+ if (vname1_length <= 1) return(ENOENT);
+ if (vname1_length >= SYMLINK_MAX) return(ENAMETOOLONG);
+ /* Get dir inode of 'name2' */
+ if (fetch_name(vname2, vname2_length, fullpath) != OK) return(err_code);
if ((vp = last_dir(&resolve, fp)) == NULL) return(err_code);
-
if ((r = forbidden(fp, vp, W_BIT|X_BIT)) == OK) {
r = req_slink(vp->v_fs_e, vp->v_inode_nr, fullpath, who_e,
- m_in.name1, m_in.name1_length - 1, fp->fp_effuid,
+ vname1, vname1_length - 1, fp->fp_effuid,
fp->fp_effgid);
}
if ((vp->v_mode & I_TYPE) != I_SYMBOLIC_LINK)
r = EINVAL;
else
- r = req_rdlink(vp->v_fs_e, vp->v_inode_nr, NONE, link_path,
+ r = req_rdlink(vp->v_fs_e, vp->v_inode_nr, NONE, (vir_bytes) link_path,
PATH_MAX - 1, 1);
if (r > 0) link_path[r] = '\0'; /* Terminate string when succesful */
int do_rdlink()
{
/* Perform the readlink(name, buf, bufsize) system call. */
- int r, copylen;
+ int r;
struct vnode *vp;
struct vmnt *vmp;
char fullpath[PATH_MAX];
struct lookup resolve;
+ vir_bytes vname;
+ size_t vname_length, buf_size;
+ vir_bytes buf;
+
+ vname = (vir_bytes) job_m_in.name1;
+ vname_length = job_m_in.name1_length;
+ buf = (vir_bytes) job_m_in.name2;
+ buf_size = (size_t) job_m_in.nbytes;
+ if (buf_size > SSIZE_MAX) return(EINVAL);
lookup_init(&resolve, fullpath, PATH_RET_SYMLINK, &vmp, &vp);
resolve.l_vmnt_lock = VMNT_READ;
resolve.l_vnode_lock = VNODE_READ;
- copylen = m_in.nbytes;
- if (copylen < 0) return(EINVAL);
-
/* Temporarily open the file containing the symbolic link */
- if (fetch_name(m_in.name1, m_in.name1_length, M1, fullpath) != OK)
- return(err_code);
+ if (fetch_name(vname, vname_length, fullpath) != OK) return(err_code);
if ((vp = eat_path(&resolve, fp)) == NULL) return(err_code);
/* Make sure this is a symbolic link */
if ((vp->v_mode & I_TYPE) != I_SYMBOLIC_LINK)
r = EINVAL;
else
- r = req_rdlink(vp->v_fs_e, vp->v_inode_nr, who_e, m_in.name2,
- copylen, 0);
+ r = req_rdlink(vp->v_fs_e, vp->v_inode_nr, who_e, buf, buf_size, 0);
unlock_vnode(vp);
unlock_vmnt(vmp);
#endif
/* Thread related prototypes */
-static void thread_cleanup_f(struct fproc *rfp, char *f, int l);
-#define thread_cleanup(x) thread_cleanup_f(x, __FILE__, __LINE__)
+static void thread_cleanup(struct fproc *rfp);
static void *do_async_dev_result(void *arg);
static void *do_control_msgs(void *arg);
static void *do_fs_reply(struct job *job);
/* This is the main loop that gets work, processes it, and sends replies. */
while (TRUE) {
yield_all(); /* let other threads run */
+ self = NULL;
send_work();
get_work();
/* Handle asynchronous device replies and new system calls. If the originating
* endpoint is an FS endpoint, take extra care not to get in deadlock. */
struct vmnt *vmp = NULL;
+ endpoint_t proc_e;
- if ((vmp = find_vmnt(who_e)) != NULL) {
+ proc_e = m_in.m_source;
+
+ if ((vmp = find_vmnt(proc_e)) != NULL) {
/* A call back or dev result from an FS endpoint */
/* Set call back flag. We assume that an FS does only one call back
/* Already trying to resolve a deadlock, can't
* handle more, sorry */
vmp->m_flags &= ~VMNT_CALLBACK;
- reply(who_e, EAGAIN);
+ reply(proc_e, EAGAIN);
return;
}
deadlock_resolving = 1;
}
/*===========================================================================*
- * do_async_dev_result *
+ * do_async_dev_result *
*===========================================================================*/
static void *do_async_dev_result(void *arg)
{
my_job = *((struct job *) arg);
fp = my_job.j_fp;
- m_in = my_job.j_m_in;
/* An asynchronous character driver has results for us */
- if (call_nr == DEV_REVIVE) {
- endpt = m_in.REP_ENDPT;
+ if (job_call_nr == DEV_REVIVE) {
+ endpt = job_m_in.REP_ENDPT;
if (endpt == VFS_PROC_NR)
- endpt = find_suspended_ep(m_in.m_source, m_in.REP_IO_GRANT);
+ endpt = find_suspended_ep(job_m_in.m_source,
+ job_m_in.REP_IO_GRANT);
if (endpt == NONE) {
printf("VFS: proc with grant %d from %d not found\n",
- m_in.REP_IO_GRANT, m_in.m_source);
- } else if (m_in.REP_STATUS == SUSPEND) {
+ job_m_in.REP_IO_GRANT, job_m_in.m_source);
+ } else if (job_m_in.REP_STATUS == SUSPEND) {
printf("VFS: got SUSPEND on DEV_REVIVE: not reviving proc\n");
} else
- revive(endpt, m_in.REP_STATUS);
+ revive(endpt, job_m_in.REP_STATUS);
}
- else if (call_nr == DEV_OPEN_REPL) open_reply();
- else if (call_nr == DEV_REOPEN_REPL) reopen_reply();
- else if (call_nr == DEV_CLOSE_REPL) close_reply();
- else if (call_nr == DEV_SEL_REPL1)
- select_reply1(m_in.m_source, m_in.DEV_MINOR, m_in.DEV_SEL_OPS);
- else if (call_nr == DEV_SEL_REPL2)
- select_reply2(m_in.m_source, m_in.DEV_MINOR, m_in.DEV_SEL_OPS);
+ else if (job_call_nr == DEV_OPEN_REPL) open_reply();
+ else if (job_call_nr == DEV_REOPEN_REPL) reopen_reply();
+ else if (job_call_nr == DEV_CLOSE_REPL) close_reply();
+ else if (job_call_nr == DEV_SEL_REPL1)
+ select_reply1(job_m_in.m_source, job_m_in.DEV_MINOR,
+ job_m_in.DEV_SEL_OPS);
+ else if (job_call_nr == DEV_SEL_REPL2)
+ select_reply2(job_m_in.m_source, job_m_in.DEV_MINOR,
+ job_m_in.DEV_SEL_OPS);
if (deadlock_resolving) {
if (fp != NULL && fp->fp_wtid == dl_worker.w_tid)
my_job = *((struct job *) arg);
fp = my_job.j_fp;
- m_in = my_job.j_m_in;
/* Check for special control messages. */
- if (who_e == CLOCK) {
+ if (job_m_in.m_source == CLOCK) {
/* Alarm timer expired. Used only for select(). Check it. */
- expire_timers(m_in.NOTIFY_TIMESTAMP);
- } else if (who_e == DS_PROC_NR) {
+ expire_timers(job_m_in.NOTIFY_TIMESTAMP);
+ } else if (job_m_in.m_source == DS_PROC_NR) {
/* DS notifies us of an event. */
ds_event();
} else {
/* Device notifies us of an event. */
- dev_status(&m_in);
+ dev_status(&job_m_in);
}
thread_cleanup(NULL);
printf("VFS: expected %d to reply, not %d\n", rfp->fp_task, who_e);
*rfp->fp_sendrec = m_in;
rfp->fp_task = NONE;
- vmp->m_comm.c_cur_reqs--; /* We've got our reply, make room for others */
- worker_signal(worker_get(rfp->fp_wtid));/* Continue this worker thread */
+ vmp->m_comm.c_cur_reqs--; /* We've got our reply, make room for others */
+ if (rfp->fp_wtid != invalid_thread_id)
+ worker_signal(worker_get(rfp->fp_wtid)); /* Continue this thread */
return(NULL);
}
*===========================================================================*/
static void lock_pm(void)
{
- message org_m_in;
struct fproc *org_fp;
struct worker_thread *org_self;
if (mutex_trylock(&pm_lock) == 0)
return;
- org_m_in = m_in;
org_fp = fp;
org_self = self;
if (mutex_lock(&pm_lock) != 0)
panic("Could not obtain lock on pm\n");
- m_in = org_m_in;
fp = org_fp;
self = org_self;
}
my_job = *((struct job *) arg);
rfp = fp = my_job.j_fp;
- m_in = my_job.j_m_in;
lock_pm();
service_pm();
}
/*===========================================================================*
- * do_pending_pipe *
+ * do_pending_pipe *
*===========================================================================*/
static void *do_pending_pipe(void *arg)
{
my_job = *((struct job *) arg);
fp = my_job.j_fp;
- m_in = my_job.j_m_in;
lock_proc(fp, 1 /* force lock */);
assert(f != NULL);
scratch(fp).file.filp = NULL;
- locktype = (call_nr == READ) ? VNODE_READ : VNODE_WRITE;
- op = (call_nr == READ) ? READING : WRITING;
+ locktype = (job_call_nr == READ) ? VNODE_READ : VNODE_WRITE;
+ op = (job_call_nr == READ) ? READING : WRITING;
lock_filp(f, locktype);
r = rw_pipe(op, who_e, f, scratch(fp).io.io_buffer, scratch(fp).io.io_nbytes);
if (r != SUSPEND) /* Do we have results to report? */
- reply(who_e, r);
+ reply(fp->fp_endpoint, r);
unlock_filp(f);
my_job = *((struct job *) arg);
fp = my_job.j_fp;
- m_in = my_job.j_m_in;
if ((r = mutex_trylock(&fp->fp_lock)) == 0) {
thread_cleanup(fp);
my_job = *((struct job *) arg);
fp = my_job.j_fp;
- m_in = my_job.j_m_in;
lock_proc(fp, 0); /* This proc is busy */
- if (call_nr == MAPDRIVER) {
+ if (job_call_nr == MAPDRIVER) {
error = do_mapdriver();
- } else if (call_nr == COMMON_GETSYSINFO) {
+ } else if (job_call_nr == COMMON_GETSYSINFO) {
error = do_getsysinfo();
- } else if (IS_PFS_VFS_RQ(call_nr)) {
+ } else if (IS_PFS_VFS_RQ(job_call_nr)) {
if (who_e != PFS_PROC_NR) {
printf("VFS: only PFS is allowed to make nested VFS calls\n");
error = ENOSYS;
- } else if (call_nr <= PFS_BASE || call_nr >= PFS_BASE + PFS_NREQS) {
+ } else if (job_call_nr <= PFS_BASE ||
+ job_call_nr >= PFS_BASE + PFS_NREQS) {
error = ENOSYS;
} else {
- call_nr -= PFS_BASE;
- error = (*pfs_call_vec[call_nr])();
+ job_call_nr -= PFS_BASE;
+ error = (*pfs_call_vec[job_call_nr])();
}
} else {
/* We're dealing with a POSIX system call from a normal
* process. Call the internal function that does the work.
*/
- if (call_nr < 0 || call_nr >= NCALLS) {
+ if (job_call_nr < 0 || job_call_nr >= NCALLS) {
error = ENOSYS;
} else if (fp->fp_pid == PID_FREE) {
/* Process vanished before we were able to handle request.
error = SUSPEND;
} else {
#if ENABLE_SYSCALL_STATS
- calls_stats[call_nr]++;
+ calls_stats[job_call_nr]++;
#endif
- error = (*call_vec[call_nr])();
+ error = (*call_vec[job_call_nr])();
}
}
if (fp->fp_wtid == dl_worker.w_tid)
deadlock_resolving = 0;
}
- reply(who_e, error);
+
+ reply(fp->fp_endpoint, error);
}
thread_cleanup(fp);
force_sync = 0;
receive_from = ANY;
+ self = NULL;
/* Initialize proc endpoints to NONE */
for (rfp = &fproc[0]; rfp < &fproc[NR_PROCS]; rfp++) {
s = ds_subscribe("drv\\.[bc]..\\..*", DSF_INITIAL | DSF_OVERWRITE);
if (s != OK) panic("VFS: can't subscribe to driver events (%d)", s);
-#if DO_SANITYCHECKS
- FIXME("VFS: DO_SANITYCHECKS is on");
-#endif
-
/* Initialize worker threads */
for (i = 0; i < NR_WTHREADS; i++) {
worker_init(&workers[i]);
mount_pfs(); /* mount Pipe File Server */
worker_start(do_init_root); /* mount initial ramdisk as file system root */
yield(); /* force do_init_root to start */
+ self = NULL;
return(OK);
}
void lock_proc(struct fproc *rfp, int force_lock)
{
int r;
- message org_m_in;
struct fproc *org_fp;
struct worker_thread *org_self;
if (r == 0) return;
- org_m_in = m_in;
org_fp = fp;
org_self = self;
+
if ((r = mutex_lock(&rfp->fp_lock)) != 0)
panic("unable to lock fproc lock: %d", r);
- m_in = org_m_in;
+
fp = org_fp;
self = org_self;
}
/*===========================================================================*
* thread_cleanup *
*===========================================================================*/
-static void thread_cleanup_f(struct fproc *rfp, char *f, int l)
+static void thread_cleanup(struct fproc *rfp)
{
/* Clean up worker thread. Skip parts if this thread is not associated
* with a particular process (i.e., rfp is NULL) */
- assert(mthread_self() != -1);
-
#if LOCK_DEBUG
if (rfp != NULL) {
check_filp_locks_by_me();
#endif
if (rfp != NULL && rfp->fp_flags & FP_PM_PENDING) { /* Postponed PM call */
- m_in = rfp->fp_job.j_m_in;
+ job_m_in = rfp->fp_job.j_m_in;
rfp->fp_flags &= ~FP_PM_PENDING;
service_pm_postponed();
}
rfp->fp_flags &= ~FP_DROP_WORK;
unlock_proc(rfp);
}
-
-#if 0
- mthread_exit(NULL);
-#endif
}
/*===========================================================================*
if (who_p >= (int)(sizeof(fproc) / sizeof(struct fproc)))
panic("receive process out of range: %d", who_p);
if (who_p >= 0 && fproc[who_p].fp_endpoint == NONE) {
- printf("VFS: ignoring request from %d, endpointless slot %d (%d)\n",
+ printf("VFS: ignoring request from %d: NONE endpoint %d (%d)\n",
m_in.m_source, who_p, m_in.m_type);
continue;
}
}
}
-
/*===========================================================================*
* reply *
*===========================================================================*/
-void reply(whom, result)
-int whom; /* process to reply to */
-int result; /* result of the call (usually OK or error #) */
+void reply(endpoint_t whom, int result)
{
/* Send a reply to a user process. If the send fails, just ignore it. */
int r;
m_out.reply_type = result;
r = sendnb(whom, &m_out);
if (r != OK) {
- printf("VFS: couldn't send reply %d to %d: %d\n", result, whom, r);
+ printf("VFS: %d couldn't send reply %d to %d: %d\n", mthread_self(),
+ result, whom, r);
+ util_stacktrace();
}
}
int r;
vir_bytes pc;
- switch(call_nr) {
+ switch(job_call_nr) {
case PM_EXEC:
- r = pm_exec(m_in.PM_PROC, m_in.PM_PATH, m_in.PM_PATH_LEN,
- m_in.PM_FRAME, m_in.PM_FRAME_LEN, &pc);
-
- /* Reply status to PM */
- m_out.m_type = PM_EXEC_REPLY;
- m_out.PM_PROC = m_in.PM_PROC;
- m_out.PM_PC = (void*)pc;
- m_out.PM_STATUS = r;
-
+ {
+ endpoint_t proc_e;
+ vir_bytes exec_path, stack_frame;
+ size_t exec_path_len, stack_frame_len;
+
+ proc_e = job_m_in.PM_PROC;
+ exec_path = (vir_bytes) job_m_in.PM_PATH;
+ exec_path_len = (size_t) job_m_in.PM_PATH_LEN;
+ stack_frame = (vir_bytes) job_m_in.PM_FRAME;
+ stack_frame_len = (size_t) job_m_in.PM_FRAME_LEN;
+
+ r = pm_exec(proc_e, exec_path, exec_path_len, stack_frame,
+ stack_frame_len, &pc);
+
+ /* Reply status to PM */
+ m_out.m_type = PM_EXEC_REPLY;
+ m_out.PM_PROC = proc_e;
+ m_out.PM_PC = (void*) pc;
+ m_out.PM_STATUS = r;
+ }
break;
case PM_EXIT:
- pm_exit(m_in.PM_PROC);
+ {
+ endpoint_t proc_e;
+ proc_e = job_m_in.PM_PROC;
- /* Reply dummy status to PM for synchronization */
- m_out.m_type = PM_EXIT_REPLY;
- m_out.PM_PROC = m_in.PM_PROC;
+ pm_exit(proc_e);
+ /* Reply dummy status to PM for synchronization */
+ m_out.m_type = PM_EXIT_REPLY;
+ m_out.PM_PROC = proc_e;
+ }
break;
case PM_DUMPCORE:
- /* Copy parameters first. m_in gets overwritten when creating core
- * file.
- */
-
- r = pm_dumpcore(m_in.PM_PROC, m_in.PM_TERM_SIG,
- (vir_bytes) m_in.PM_PATH);
-
- /* Reply status to PM */
- m_out.m_type = PM_CORE_REPLY;
- m_out.PM_PROC = m_in.PM_PROC;
- m_out.PM_TRACED_PROC = m_in.PM_TRACED_PROC;
- m_out.PM_STATUS = r;
-
+ {
+ endpoint_t proc_e, traced_proc_e;
+ int term_signal;
+ vir_bytes core_path;
+
+ proc_e = job_m_in.PM_PROC;
+ traced_proc_e = job_m_in.PM_TRACED_PROC;
+ term_signal = job_m_in.PM_TERM_SIG;
+ core_path = (vir_bytes) job_m_in.PM_PATH;
+
+ r = pm_dumpcore(proc_e, term_signal, core_path);
+
+ /* Reply status to PM */
+ m_out.m_type = PM_CORE_REPLY;
+ m_out.PM_PROC = proc_e;
+ m_out.PM_TRACED_PROC = traced_proc_e;
+ m_out.PM_STATUS = r;
+ }
break;
default:
- panic("Unhandled postponed PM call %d", m_in.m_type);
+ panic("Unhandled postponed PM call %d", job_m_in.m_type);
}
r = send(PM_PROC_NR, &m_out);
{
int r, slot;
- switch (call_nr) {
+ switch (job_call_nr) {
case PM_SETUID:
- pm_setuid(m_in.PM_PROC, m_in.PM_EID, m_in.PM_RID);
+ {
+ endpoint_t proc_e;
+ uid_t euid, ruid;
+
+ proc_e = job_m_in.PM_PROC;
+ euid = job_m_in.PM_EID;
+ ruid = job_m_in.PM_RID;
- m_out.m_type = PM_SETUID_REPLY;
- m_out.PM_PROC = m_in.PM_PROC;
+ pm_setuid(proc_e, euid, ruid);
+ m_out.m_type = PM_SETUID_REPLY;
+ m_out.PM_PROC = proc_e;
+ }
break;
case PM_SETGID:
- pm_setgid(m_in.PM_PROC, m_in.PM_EID, m_in.PM_RID);
+ {
+ endpoint_t proc_e;
+ gid_t egid, rgid;
+
+ proc_e = job_m_in.PM_PROC;
+ egid = job_m_in.PM_EID;
+ rgid = job_m_in.PM_RID;
- m_out.m_type = PM_SETGID_REPLY;
- m_out.PM_PROC = m_in.PM_PROC;
+ pm_setgid(proc_e, egid, rgid);
+ m_out.m_type = PM_SETGID_REPLY;
+ m_out.PM_PROC = proc_e;
+ }
break;
case PM_SETSID:
- pm_setsid(m_in.PM_PROC);
+ {
+ endpoint_t proc_e;
- m_out.m_type = PM_SETSID_REPLY;
- m_out.PM_PROC = m_in.PM_PROC;
+ proc_e = job_m_in.PM_PROC;
+ pm_setsid(proc_e);
+ m_out.m_type = PM_SETSID_REPLY;
+ m_out.PM_PROC = proc_e;
+ }
break;
case PM_EXEC:
case PM_EXIT:
case PM_DUMPCORE:
- okendpt(m_in.PM_PROC, &slot);
- fp = &fproc[slot];
-
- if (fp->fp_flags & FP_PENDING) {
- /* This process has a request pending, but PM wants it gone.
- * Forget about the pending request and satisfy PM's request
- * instead. Note that a pending request AND an EXEC request
- * are mutually exclusive. Also, PM should send only one
- * request/process at a time.
- */
- assert(fp->fp_job.j_m_in.m_source != PM_PROC_NR);
- }
-
- /* PM requests on behalf of a proc are handled after the system call
- * that might be in progress for that proc has finished. If the proc
- * is not busy, we start a dummy call */
- if (!(fp->fp_flags & FP_PENDING) && mutex_trylock(&fp->fp_lock) == 0) {
- mutex_unlock(&fp->fp_lock);
- worker_start(do_dummy);
- fp->fp_flags |= FP_DROP_WORK;
- }
+ {
+ endpoint_t proc_e = job_m_in.PM_PROC;
+ okendpt(proc_e, &slot);
+ fp = &fproc[slot];
+
+ if (fp->fp_flags & FP_PENDING) {
+ /* This process has a request pending, but PM wants it
+ * gone. Forget about the pending request and satisfy
+ * PM's request instead. Note that a pending request
+ * AND an EXEC request are mutually exclusive. Also, PM
+ * should send only one request/process at a time.
+ */
+ assert(fp->fp_job.j_m_in.m_source != PM_PROC_NR);
+ }
- fp->fp_job.j_m_in = m_in;
- fp->fp_flags |= FP_PM_PENDING;
+ /* PM requests on behalf of a proc are handled after the
+ * system call that might be in progress for that proc has
+ * finished. If the proc is not busy, we start a dummy call.
+ */
+ if (!(fp->fp_flags & FP_PENDING) &&
+ mutex_trylock(&fp->fp_lock) == 0) {
+ mutex_unlock(&fp->fp_lock);
+ worker_start(do_dummy);
+ fp->fp_flags |= FP_DROP_WORK;
+ }
- return;
+ fp->fp_job.j_m_in = job_m_in;
+ fp->fp_flags |= FP_PM_PENDING;
+ return;
+ }
case PM_FORK:
case PM_SRV_FORK:
- pm_fork(m_in.PM_PPROC, m_in.PM_PROC, m_in.PM_CPID);
- m_out.m_type = PM_FORK_REPLY;
+ {
+ endpoint_t pproc_e, proc_e;
+ pid_t child_pid;
+ uid_t reuid;
+ gid_t regid;
+
+ pproc_e = job_m_in.PM_PPROC;
+ proc_e = job_m_in.PM_PROC;
+ child_pid = job_m_in.PM_CPID;
+ reuid = job_m_in.PM_REUID;
+ regid = job_m_in.PM_REGID;
+
+ pm_fork(pproc_e, proc_e, child_pid);
+ m_out.m_type = PM_FORK_REPLY;
+
+ if (job_call_nr == PM_SRV_FORK) {
+ m_out.m_type = PM_SRV_FORK_REPLY;
+ pm_setuid(proc_e, reuid, reuid);
+ pm_setgid(proc_e, regid, regid);
+ }
- if (call_nr == PM_SRV_FORK) {
- m_out.m_type = PM_SRV_FORK_REPLY;
- pm_setuid(m_in.PM_PROC, m_in.PM_REUID, m_in.PM_REUID);
- pm_setgid(m_in.PM_PROC, m_in.PM_REGID, m_in.PM_REGID);
+ m_out.PM_PROC = proc_e;
}
-
- m_out.PM_PROC = m_in.PM_PROC;
-
break;
case PM_SETGROUPS:
- pm_setgroups(m_in.PM_PROC, m_in.PM_GROUP_NO,
- (gid_t *) m_in.PM_GROUP_ADDR);
+ {
+ endpoint_t proc_e;
+ int group_no;
+ gid_t *group_addr;
- m_out.m_type = PM_SETGROUPS_REPLY;
- m_out.PM_PROC = m_in.PM_PROC;
+ proc_e = job_m_in.PM_PROC;
+ group_no = job_m_in.PM_GROUP_NO;
+ group_addr = (gid_t *) job_m_in.PM_GROUP_ADDR;
+ pm_setgroups(proc_e, group_no, group_addr);
+
+ m_out.m_type = PM_SETGROUPS_REPLY;
+ m_out.PM_PROC = proc_e;
+ }
break;
case PM_UNPAUSE:
- unpause(m_in.PM_PROC);
+ {
+ endpoint_t proc_e;
+
+ proc_e = job_m_in.PM_PROC;
- m_out.m_type = PM_UNPAUSE_REPLY;
- m_out.PM_PROC = m_in.PM_PROC;
+ unpause(proc_e);
+ m_out.m_type = PM_UNPAUSE_REPLY;
+ m_out.PM_PROC = proc_e;
+ }
break;
case PM_REBOOT:
break;
default:
- printf("VFS: don't know how to handle PM request %d\n", call_nr);
+ printf("VFS: don't know how to handle PM request %d\n", job_call_nr);
return;
}
fp = rfp;
blocked_on = rfp->fp_blocked_on;
+ m_in.m_source = rfp->fp_endpoint;
m_in.m_type = rfp->fp_block_callnr;
+ if (call_nr == 6) { /* close() */
+ if (m_in.fd != scratch(fp).file.fd_nr)
+ printf("VFS: would've done something weird\n");
+ }
m_in.fd = scratch(fp).file.fd_nr;
m_in.buffer = scratch(fp).io.io_buffer;
m_in.nbytes = scratch(fp).io.io_nbytes;
if (blocked_on == FP_BLOCKED_ON_PIPE) {
worker_start(do_pending_pipe);
yield(); /* Give thread a chance to run */
+ self = NULL;
return(0); /* Retrieve more work */
}
int do_getsysinfo()
{
vir_bytes src_addr, dst_addr;
- size_t len;
+ size_t len, buf_size;
+ int what;
+
+ what = job_m_in.SI_WHAT;
+ dst_addr = (vir_bytes) job_m_in.SI_WHERE;
+ buf_size = (size_t) job_m_in.SI_SIZE;
/* Only su may call do_getsysinfo. This call may leak information (and is not
* stable enough to be part of the API/ABI). In the future, requests from
if (!super_user) return(EPERM);
- switch(m_in.SI_WHAT) {
+ switch(what) {
case SI_PROC_TAB:
src_addr = (vir_bytes) fproc;
len = sizeof(struct fproc) * NR_PROCS;
return(EINVAL);
}
- if (len != m_in.SI_SIZE)
+ if (len != buf_size)
return(EINVAL);
- dst_addr = (vir_bytes) m_in.SI_WHERE;
return sys_datacopy(SELF, src_addr, who_e, dst_addr, len);
}
* provided to permit old binary programs to continue to run.
*/
- register int rfd;
- register struct filp *f;
+ int rfd, rfd2;
+ struct filp *f;
int r = OK;
+ scratch(fp).file.fd_nr = job_m_in.fd;
+ rfd2 = job_m_in.fd2;
+
/* Is the file descriptor valid? */
- rfd = m_in.fd & ~DUP_MASK; /* kill off dup2 bit, if on */
+ rfd = scratch(fp).file.fd_nr & ~DUP_MASK; /* kill off dup2 bit, if on */
if ((f = get_filp(rfd, VNODE_READ)) == NULL) return(err_code);
/* Distinguish between dup and dup2. */
- if (m_in.fd == rfd) { /* bit not on */
+ if (!(scratch(fp).file.fd_nr & DUP_MASK)) { /* bit not on */
/* dup(fd) */
- r = get_fd(0, 0, &m_in.fd2, NULL);
+ r = get_fd(0, 0, &rfd2, NULL);
} else {
/* dup2(old_fd, new_fd) */
- if (m_in.fd2 < 0 || m_in.fd2 >= OPEN_MAX) {
+ if (rfd2 < 0 || rfd2 >= OPEN_MAX) {
r = EBADF;
- } else if (rfd == m_in.fd2) { /* ignore the call: dup2(x, x) */
- r = m_in.fd2;
+ } else if (rfd == rfd2) { /* ignore the call: dup2(x, x) */
+ r = rfd2;
} else {
/* All is fine, close new_fd if necessary */
- m_in.fd = m_in.fd2; /* prepare to close fd2 */
unlock_filp(f); /* or it might deadlock on do_close */
- (void) do_close(); /* cannot fail */
+ (void) close_fd(fp, rfd2); /* cannot fail */
f = get_filp(rfd, VNODE_READ); /* lock old_fd again */
}
}
if (r == OK) {
/* Success. Set up new file descriptors. */
f->filp_count++;
- fp->fp_filp[m_in.fd2] = f;
- FD_SET(m_in.fd2, &fp->fp_filp_inuse);
- r = m_in.fd2;
+ fp->fp_filp[rfd2] = f;
+ FD_SET(rfd2, &fp->fp_filp_inuse);
+ r = rfd2;
}
unlock_filp(f);
/* Perform the fcntl(fd, request, ...) system call. */
register struct filp *f;
- int new_fd, fl, r = OK;
+ int new_fd, fl, r = OK, fcntl_req, fcntl_argx;
tll_access_t locktype;
- scratch(fp).file.fd_nr = m_in.fd;
- scratch(fp).io.io_buffer = m_in.buffer;
- scratch(fp).io.io_nbytes = m_in.nbytes; /* a.k.a. m_in.request */
+ scratch(fp).file.fd_nr = job_m_in.fd;
+ scratch(fp).io.io_buffer = job_m_in.buffer;
+ scratch(fp).io.io_nbytes = job_m_in.nbytes; /* a.k.a. m_in.request */
+ fcntl_req = job_m_in.request;
+ fcntl_argx = job_m_in.addr;
/* Is the file descriptor valid? */
- locktype = (m_in.request == F_FREESP) ? VNODE_WRITE : VNODE_READ;
+ locktype = (fcntl_req == F_FREESP) ? VNODE_WRITE : VNODE_READ;
if ((f = get_filp(scratch(fp).file.fd_nr, locktype)) == NULL)
return(err_code);
- switch (m_in.request) {
+ switch (fcntl_req) {
case F_DUPFD:
/* This replaces the old dup() system call. */
- if (m_in.addr < 0 || m_in.addr >= OPEN_MAX) r = EINVAL;
- else if ((r = get_fd(m_in.addr, 0, &new_fd, NULL)) == OK) {
+ if (fcntl_argx < 0 || fcntl_argx >= OPEN_MAX) r = EINVAL;
+ else if ((r = get_fd(fcntl_argx, 0, &new_fd, NULL)) == OK) {
f->filp_count++;
fp->fp_filp[new_fd] = f;
FD_SET(new_fd, &fp->fp_filp_inuse);
case F_SETFD:
/* Set close-on-exec flag (FD_CLOEXEC in POSIX Table 6-2). */
- if(m_in.addr & FD_CLOEXEC)
+ if (fcntl_argx & FD_CLOEXEC)
FD_SET(scratch(fp).file.fd_nr, &fp->fp_cloexec_set);
else
FD_CLR(scratch(fp).file.fd_nr, &fp->fp_cloexec_set);
case F_SETFL:
/* Set file status flags (O_NONBLOCK and O_APPEND). */
fl = O_NONBLOCK | O_APPEND | O_REOPEN;
- f->filp_flags = (f->filp_flags & ~fl) | (m_in.addr & fl);
+ f->filp_flags = (f->filp_flags & ~fl) | (fcntl_argx & fl);
break;
case F_GETLK:
case F_SETLK:
case F_SETLKW:
/* Set or clear a file lock. */
- r = lock_op(f, m_in.request);
+ r = lock_op(f, fcntl_req);
break;
case F_FREESP:
else if (!(f->filp_mode & W_BIT)) r = EBADF;
else
/* Copy flock data from userspace. */
- r = sys_datacopy(who_e, (vir_bytes) m_in.name1, SELF,
- (vir_bytes) &flock_arg,
- (phys_bytes) sizeof(flock_arg));
+ r = sys_datacopy(who_e, (vir_bytes) scratch(fp).io.io_buffer,
+ SELF, (vir_bytes) &flock_arg,
+ sizeof(flock_arg));
if (r != OK) break;
dev_t dev;
int r = OK;
- if ((rfilp = get_filp(m_in.m1_i1, VNODE_READ)) == NULL) return(err_code);
+ scratch(fp).file.fd_nr = job_m_in.fd;
+
+ if ((rfilp = get_filp(scratch(fp).file.fd_nr, VNODE_READ)) == NULL)
+ return(err_code);
dev = rfilp->filp_vno->v_dev;
for (vmp = &vmnt[0]; vmp < &vmnt[NR_MNTS]; ++vmp) {
if (vmp->m_dev != NO_DEV && vmp->m_dev == dev &&
/*===========================================================================*
* pm_fork *
*===========================================================================*/
-void pm_fork(pproc, cproc, cpid)
-int pproc; /* Parent process */
-int cproc; /* Child process */
-int cpid; /* Child process id */
+void pm_fork(endpoint_t pproc, endpoint_t cproc, pid_t cpid)
{
/* Perform those aspects of the fork() system call that relate to files.
* In particular, let the child inherit its parent's file descriptors.
* system uses the same slot numbers as the kernel. Only PM makes this call.
*/
- register struct fproc *cp, *pp;
+ struct fproc *cp, *pp;
int i, parentno, childno;
mutex_t c_fp_lock;
*/
childno = _ENDPOINT_P(cproc);
if (childno < 0 || childno >= NR_PROCS)
- panic("VFS: bogus child for forking: %d", m_in.child_endpt);
+ panic("VFS: bogus child for forking: %d", cproc);
if (fproc[childno].fp_pid != PID_FREE)
panic("VFS: forking on top of in-use child: %d", childno);
/* A forking process never has an outstanding grant, as it isn't blocking on
* I/O. */
- if(GRANT_VALID(pp->fp_grant)) {
+ if (GRANT_VALID(pp->fp_grant)) {
panic("VFS: fork: pp (endpoint %d) has grant %d\n", pp->fp_endpoint,
pp->fp_grant);
}
- if(GRANT_VALID(cp->fp_grant)) {
+ if (GRANT_VALID(cp->fp_grant)) {
panic("VFS: fork: cp (endpoint %d) has grant %d\n", cp->fp_endpoint,
cp->fp_grant);
}
*===========================================================================*/
int do_svrctl()
{
- switch (m_in.svrctl_req) {
+ int svrctl;
+
+ svrctl = m_in.svrctl_req;
+
+ switch (svrctl) {
/* No control request implemented yet. */
default:
return(EINVAL);
char fullpath[PATH_MAX];
char mount_label[LABEL_MAX];
dev_t dev;
+ int mflags;
+ vir_bytes label, vname1, vname2;
+ size_t vname1_length, vname2_length;
+
+ mflags = job_m_in.mount_flags;
+ label = (vir_bytes) job_m_in.fs_label;
+ vname1 = (vir_bytes) job_m_in.name1;
+ vname1_length = (size_t) job_m_in.name1_length;
+ vname2 = (vir_bytes) job_m_in.name2;
+ vname2_length = (size_t) job_m_in.name2_length;
/* Only the super-user may do MOUNT. */
if (!super_user) return(EPERM);
+
/* FS process' endpoint number */
- if (m_in.mount_flags & MS_LABEL16) {
+ if (mflags & MS_LABEL16) {
/* Get the label from the caller, and ask DS for the endpoint. */
- r = sys_datacopy(who_e, (vir_bytes) m_in.fs_label, SELF,
- (vir_bytes) mount_label, (phys_bytes) sizeof(mount_label));
+ r = sys_datacopy(who_e, label, SELF, (vir_bytes) mount_label,
+ sizeof(mount_label));
if (r != OK) return(r);
mount_label[sizeof(mount_label)-1] = 0;
if (r != OK) return(r);
} else {
/* Legacy support: get the endpoint from the request itself. */
- fs_e = (endpoint_t) m_in.fs_label;
+ fs_e = (endpoint_t) label;
mount_label[0] = 0;
}
if (isokendpt(fs_e, &slot) != OK) return(EINVAL);
/* Should the file system be mounted read-only? */
- rdonly = (m_in.mount_flags & MS_RDONLY);
+ rdonly = (mflags & MS_RDONLY);
/* A null string for block special device means don't use a device at all. */
- nodev = (m_in.name1_length == 0);
+ nodev = (vname1_length == 0);
if (!nodev) {
/* If 'name' is not for a block special file, return error. */
- if (fetch_name(m_in.name1, m_in.name1_length, M1, fullpath) != OK)
+ if (fetch_name(vname1, vname1_length, fullpath) != OK)
return(err_code);
if ((dev = name_to_dev(FALSE /*allow_mountpt*/, fullpath)) == NO_DEV)
return(err_code);
}
/* Fetch the name of the mountpoint */
- if (fetch_name(m_in.name2, m_in.name2_length, M1, fullpath) != OK)
- return(err_code);
+ if (fetch_name(vname2, vname2_length, fullpath) != OK) return(err_code);
/* Do the actual job */
return mount_fs(dev, fullpath, fs_e, rdonly, mount_label);
*===========================================================================*/
int do_umount(void)
{
-/* Perform the umount(name) system call. */
+/* Perform the umount(name) system call.
+ * syscall might provide 'name' embedded in the message.
+ */
char label[LABEL_MAX];
dev_t dev;
int r;
char fullpath[PATH_MAX];
+ vir_bytes vname;
+ size_t vname_length;
+
+ vname = (vir_bytes) job_m_in.name;
+ vname_length = (size_t) job_m_in.name_length;
/* Only the super-user may do umount. */
if (!super_user) return(EPERM);
/* If 'name' is not for a block special file or mountpoint, return error. */
- if (fetch_name(m_in.name, m_in.name_length, M3, fullpath) != OK)
- return(err_code);
+ if (copy_name(vname_length, fullpath) != OK) {
+ /* Direct copy failed, try fetching from user space */
+ if (fetch_name(vname, vname_length, fullpath) != OK)
+ return(err_code);
+ }
if ((dev = name_to_dev(TRUE /*allow_mountpt*/, fullpath)) == NO_DEV)
return(err_code);
*===========================================================================*/
int do_creat()
{
-/* Perform the creat(name, mode) system call. */
- int r;
+/* Perform the creat(name, mode) system call.
+ * syscall might provide 'name' embedded in the message.
+ */
+
char fullpath[PATH_MAX];
+ vir_bytes vname;
+ size_t vname_length;
+ mode_t open_mode;
- if (fetch_name(m_in.name, m_in.name_length, M3, fullpath) != OK)
- return(err_code);
- r = common_open(fullpath, O_WRONLY | O_CREAT | O_TRUNC, (mode_t) m_in.mode);
- return(r);
-}
+ vname = (vir_bytes) job_m_in.name;
+ vname_length = (size_t) job_m_in.name_length;
+ open_mode = (mode_t) job_m_in.mode;
+
+ if (copy_name(vname_length, fullpath) != OK) {
+ /* Direct copy failed, try fetching from user space */
+ if (fetch_name(vname, vname_length, fullpath) != OK)
+ return(err_code);
+ }
+ return common_open(fullpath, O_WRONLY | O_CREAT | O_TRUNC, open_mode);
+}
/*===========================================================================*
* do_open *
*===========================================================================*/
int do_open()
{
-/* Perform the open(name, flags,...) system call. */
- int create_mode = 0; /* is really mode_t but this gives problems */
- int r;
+/* Perform the open(name, flags,...) system call.
+ * syscall might provide 'name' embedded in message when not creating file */
+
+ int create_mode; /* is really mode_t but this gives problems */
+ int open_mode = 0; /* is really mode_t but this gives problems */
+ int r = OK;
char fullpath[PATH_MAX];
+ vir_bytes vname;
+ size_t vname_length;
+
+ open_mode = (mode_t) job_m_in.mode;
+ create_mode = job_m_in.c_mode;
/* If O_CREAT is set, open has three parameters, otherwise two. */
- if (m_in.mode & O_CREAT) {
- create_mode = m_in.c_mode;
- r = fetch_name(m_in.c_name, m_in.name1_length, M1, fullpath);
+ if (open_mode & O_CREAT) {
+ vname = (vir_bytes) job_m_in.name1;
+ vname_length = (size_t) job_m_in.name1_length;
+ r = fetch_name(vname, vname_length, fullpath);
} else {
- r = fetch_name(m_in.name, m_in.name_length, M3, fullpath);
+ vname = (vir_bytes) job_m_in.name;
+ vname_length = (size_t) job_m_in.name_length;
+ create_mode = 0;
+ if (copy_name(vname_length, fullpath) != OK) {
+ /* Direct copy failed, try fetching from user space */
+ if (fetch_name(vname, vname_length, fullpath) != OK)
+ r = err_code;
+ }
}
if (r != OK) return(err_code); /* name was bad */
- r = common_open(fullpath, m_in.mode, create_mode);
- return(r);
+ return common_open(fullpath, open_mode, create_mode);
}
b = (bits & R_BIT ? R_BIT : W_BIT);
filp->filp_count = 0; /* don't find self */
if ((filp2 = find_filp(vp, b)) != NULL) {
- /* Co-reader or writer found. Use it.*/
- fp->fp_filp[scratch(fp).file.fd_nr] = filp2;
- filp2->filp_count++;
- filp2->filp_vno = vp;
- filp2->filp_flags = oflags;
-
- /* v_count was incremented after the
- * vnode has been found. i_count was
- * incremented incorrectly in FS, not
- * knowing that we were going to use an
- * existing filp entry. Correct this
- * error.
- */
- unlock_vnode(vp);
- put_vnode(vp);
+ /* Co-reader or writer found. Use it.*/
+ fp->fp_filp[scratch(fp).file.fd_nr] = filp2;
+ filp2->filp_count++;
+ filp2->filp_vno = vp;
+ filp2->filp_flags = oflags;
+
+ /* v_count was incremented after the vnode
+ * has been found. i_count was incremented
+ * incorrectly in FS, not knowing that we
+ * were going to use an existing filp
+ * entry. Correct this error.
+ */
+ unlock_vnode(vp);
+ put_vnode(vp);
} else {
- /* Nobody else found. Restore filp. */
- filp->filp_count = 1;
+ /* Nobody else found. Restore filp. */
+ filp->filp_count = 1;
}
}
break;
r = req_rdlink(slp->v_fs_e,
slp->v_inode_nr,
VFS_PROC_NR,
- path,
+ (vir_bytes) path,
PATH_MAX - 1, 0);
if (r < 0) {
/* Failed to read link */
struct vmnt *vmp;
char fullpath[PATH_MAX];
struct lookup resolve;
+ vir_bytes vname1;
+ size_t vname1_length;
+ dev_t dev;
+
+ vname1 = (vir_bytes) job_m_in.name1;
+ vname1_length = (size_t) job_m_in.name1_length;
+ mode_bits = (mode_t) job_m_in.mk_mode; /* mode of the inode */
+ dev = job_m_in.m1_i3;
lookup_init(&resolve, fullpath, PATH_NOFLAGS, &vmp, &vp);
resolve.l_vmnt_lock = VMNT_WRITE;
resolve.l_vnode_lock = VNODE_READ;
/* Only the super_user may make nodes other than fifos. */
- mode_bits = (mode_t) m_in.mk_mode; /* mode of the inode */
if (!super_user && (((mode_bits & I_TYPE) != I_NAMED_PIPE) &&
((mode_bits & I_TYPE) != I_UNIX_SOCKET))) {
return(EPERM);
bits = (mode_bits & I_TYPE) | (mode_bits & ALL_MODES & fp->fp_umask);
/* Open directory that's going to hold the new node. */
- if (fetch_name(m_in.name1, m_in.name1_length, M1, fullpath) != OK)
- return(err_code);
+ if (fetch_name(vname1, vname1_length, fullpath) != OK) return(err_code);
if ((vp = last_dir(&resolve, fp)) == NULL) return(err_code);
/* Make sure that the object is a directory */
r = ENOTDIR;
} else if ((r = forbidden(fp, vp, W_BIT|X_BIT)) == OK) {
r = req_mknod(vp->v_fs_e, vp->v_inode_nr, fullpath, fp->fp_effuid,
- fp->fp_effgid, bits, m_in.mk_z0);
+ fp->fp_effgid, bits, dev);
}
unlock_vnode(vp);
struct vmnt *vmp;
char fullpath[PATH_MAX];
struct lookup resolve;
+ vir_bytes vname1;
+ size_t vname1_length;
+ mode_t dirmode;
+
+ vname1 = (vir_bytes) job_m_in.name1;
+ vname1_length = (size_t) job_m_in.name1_length;
+ dirmode = (mode_t) job_m_in.mode;
lookup_init(&resolve, fullpath, PATH_NOFLAGS, &vmp, &vp);
resolve.l_vmnt_lock = VMNT_WRITE;
resolve.l_vnode_lock = VNODE_READ;
- if (fetch_name(m_in.name1, m_in.name1_length, M1, fullpath) != OK)
- return(err_code);
- bits = I_DIRECTORY | (m_in.mode & RWX_MODES & fp->fp_umask);
+ if (fetch_name(vname1, vname1_length, fullpath) != OK) return(err_code);
+ bits = I_DIRECTORY | (dirmode & RWX_MODES & fp->fp_umask);
if ((vp = last_dir(&resolve, fp)) == NULL) return(err_code);
/* Make sure that the object is a directory */
{
/* Perform the lseek(ls_fd, offset, whence) system call. */
register struct filp *rfilp;
- int r = OK;
- long offset;
+ int r = OK, seekfd, seekwhence;
+ off_t offset;
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(m_in.ls_fd, VNODE_READ)) == NULL) return(err_code);
+ if ( (rfilp = get_filp(seekfd, VNODE_READ)) == NULL) return(err_code);
/* No lseek on pipes. */
if (rfilp->filp_vno->v_pipe == I_PIPE) {
}
/* The value of 'whence' determines the start position to use. */
- switch(m_in.whence) {
+ switch(seekwhence) {
case SEEK_SET: pos = cvu64(0); break;
case SEEK_CUR: pos = rfilp->filp_pos; break;
case SEEK_END: pos = cvul64(rfilp->filp_vno->v_size); break;
default: unlock_filp(rfilp); return(EINVAL);
}
- offset = m_in.offset_lo;
if (offset >= 0)
newpos = add64ul(pos, offset);
else
/* Perform the llseek(ls_fd, offset, whence) system call. */
register struct filp *rfilp;
u64_t pos, newpos;
- int r = OK;
+ 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;
/* Check to see if the file descriptor is valid. */
- if ( (rfilp = get_filp(m_in.ls_fd, VNODE_READ)) == NULL) return(err_code);
+ if ( (rfilp = get_filp(seekfd, VNODE_READ)) == NULL) return(err_code);
/* No lseek on pipes. */
if (rfilp->filp_vno->v_pipe == I_PIPE) {
}
/* The value of 'whence' determines the start position to use. */
- switch(m_in.whence) {
+ switch(seekwhence) {
case SEEK_SET: pos = cvu64(0); break;
case SEEK_CUR: pos = rfilp->filp_pos; break;
case SEEK_END: pos = cvul64(rfilp->filp_vno->v_size); break;
default: unlock_filp(rfilp); return(EINVAL);
}
- newpos = add64(pos, make64(m_in.offset_lo, m_in.offset_high));
+ newpos = add64(pos, make64(off_lo, off_hi));
/* Check for overflow. */
- if (( (long) m_in.offset_high > 0) && cmp64(newpos, pos) < 0)
+ if ((off_hi > 0) && cmp64(newpos, pos) < 0)
r = EINVAL;
- else if (( (long) m_in.offset_high < 0) && cmp64(newpos, pos) > 0)
+ else if ((off_hi < 0) && cmp64(newpos, pos) > 0)
r = EINVAL;
else {
rfilp->filp_pos = newpos;
{
/* Perform the close(fd) system call. */
- return close_fd(fp, m_in.fd);
+ scratch(fp).file.fd_nr = job_m_in.fd;
+ return close_fd(fp, scratch(fp).file.fd_nr);
}
}
r = req_rdlink(sym_vp->v_fs_e, sym_vp->v_inode_nr, NONE,
- resolve->l_path, PATH_MAX - 1, 1);
+ (vir_bytes) resolve->l_path, PATH_MAX - 1, 1);
if (r < 0) {
/* Failed to read link */
root_ino = 0;
/* Set user and group ids according to the system call */
- uid = (call_nr == ACCESS ? rfp->fp_realuid : rfp->fp_effuid);
- gid = (call_nr == ACCESS ? rfp->fp_realgid : rfp->fp_effgid);
+ uid = (job_call_nr == ACCESS ? rfp->fp_realuid : rfp->fp_effuid);
+ gid = (job_call_nr == ACCESS ? rfp->fp_realgid : rfp->fp_effgid);
symloop = 0; /* Number of symlinks seen so far */
*===========================================================================*/
int do_check_perms(void)
{
- return check_perms(m_in.USER_ENDPT, (cp_grant_id_t) m_in.IO_GRANT,
- (size_t) m_in.COUNT);
+ return check_perms(job_m_in.USER_ENDPT, (cp_grant_id_t) job_m_in.IO_GRANT,
+ (size_t) job_m_in.COUNT);
}
* The SUSPEND pseudo error should be returned after calling suspend().
*/
-#if DO_SANITYCHECKS
- if(fp_is_blocked(fp))
- panic("suspend: called for suspended process");
-
- if(why == FP_BLOCKED_ON_NONE)
- panic("suspend: called for FP_BLOCKED_ON_NONE");
-#endif
-
if (why == FP_BLOCKED_ON_POPEN || why == FP_BLOCKED_ON_PIPE)
/* #procs susp'ed on pipe*/
susp_count++;
fp->fp_blocked_on = why;
assert(fp->fp_grant == GRANT_INVALID || !GRANT_VALID(fp->fp_grant));
- fp->fp_block_callnr = call_nr;
+ fp->fp_block_callnr = job_call_nr;
fp->fp_flags &= ~FP_SUSP_REOPEN; /* Clear this flag. The caller
* can set it when needed.
*/
/*===========================================================================*
- * pipe_suspend *
+ * pipe_suspend *
*===========================================================================*/
void pipe_suspend(filp, buf, size)
struct filp *filp;
/* Take measures to suspend the processing of the present system call.
* Store the parameters to be used upon resuming in the process table.
*/
-#if DO_SANITYCHECKS
- if(fp_is_blocked(fp))
- panic("pipe_suspend: called for suspended process");
-#endif
scratch(fp).file.filp = filp;
scratch(fp).io.io_buffer = buf;
/*===========================================================================*
* revive *
*===========================================================================*/
-void revive(proc_nr_e, returned)
-int proc_nr_e; /* process to revive */
-int returned; /* if hanging on task, how many bytes read */
+void revive(endpoint_t proc_e, int returned)
{
/* Revive a previously blocked process. When a process hangs on tty, this
* is the way it is eventually released.
*/
- register struct fproc *rfp;
+ struct fproc *rfp;
int blocked_on;
int fd_nr, slot;
struct filp *fil_ptr;
- if (proc_nr_e == NONE || isokendpt(proc_nr_e, &slot) != OK) return;
+ if (proc_e == NONE || isokendpt(proc_e, &slot) != OK) return;
rfp = &fproc[slot];
if (!fp_is_blocked(rfp) || (rfp->fp_flags & FP_REVIVED)) return;
unlock_filp(fil_ptr);
put_vnode(fil_ptr->filp_vno);
fil_ptr->filp_vno = NULL;
- reply(proc_nr_e, returned);
+ reply(proc_e, returned);
} else {
- reply(proc_nr_e, fd_nr);
+ reply(proc_e, fd_nr);
}
} else {
rfp->fp_blocked_on = FP_BLOCKED_ON_NONE;
scratch(rfp).file.fd_nr = 0;
if (blocked_on == FP_BLOCKED_ON_POPEN) {
/* process blocked in open or create */
- reply(proc_nr_e, fd_nr);
+ reply(proc_e, fd_nr);
} else if (blocked_on == FP_BLOCKED_ON_SELECT) {
- reply(proc_nr_e, returned);
+ reply(proc_e, returned);
} else {
/* Revive a process suspended on TTY or other device.
* Pretend it wants only what there is.
}
rfp->fp_grant = GRANT_INVALID;
}
- reply(proc_nr_e, returned); /* unblock the process */
+ reply(proc_e, returned);/* unblock the process */
}
}
}
reply(proc_e, status); /* signal interrupted call */
}
-#if DO_SANITYCHECKS
-/*===========================================================================*
- * check_pipe *
- *===========================================================================*/
-int check_pipe(void)
-{
-/* Integrity check; verify that susp_count equals what the fproc table thinks
- * is suspended on a pipe */
- struct fproc *rfp;
- int count = 0;
- for (rfp = &fproc[0]; rfp < &fproc[NR_PROCS]; rfp++) {
- if (rfp->fp_pid == PID_FREE) continue;
- if ( !(rfp->fp_flags & FP_REVIVED) &&
- (rfp->fp_blocked_on == FP_BLOCKED_ON_PIPE ||
- rfp->fp_blocked_on == FP_BLOCKED_ON_POPEN)) {
- count++;
- }
- }
-
- if (count != susp_count) {
- printf("check_pipe: count %d susp_count %d\n", count, susp_count);
- return(0);
- }
-
- return(l);
-}
-#endif
*===========================================================================*/
int do_chmod()
{
-/* Perform the chmod(name, mode) and fchmod(fd, mode) system calls. */
+/* Perform the chmod(name, mode) and fchmod(fd, mode) system calls.
+ * syscall might provide 'name' embedded in the message.
+ */
struct filp *flp;
struct vnode *vp;
struct vmnt *vmp;
- int r;
- mode_t new_mode;
+ int r, rfd;
+ mode_t result_mode;
char fullpath[PATH_MAX];
struct lookup resolve;
+ vir_bytes vname;
+ size_t vname_length;
+ mode_t new_mode;
flp = NULL;
+ vname = (vir_bytes) job_m_in.name;
+ vname_length = (size_t) job_m_in.name_length;
+ rfd = job_m_in.fd;
+ new_mode = (mode_t) job_m_in.mode;
lookup_init(&resolve, fullpath, PATH_NOFLAGS, &vmp, &vp);
resolve.l_vmnt_lock = VMNT_WRITE;
resolve.l_vnode_lock = VNODE_WRITE;
- if (call_nr == CHMOD) {
+ if (job_call_nr == CHMOD) {
/* Temporarily open the file */
- if (fetch_name(m_in.name, m_in.name_length, M3, fullpath) != OK)
- return(err_code);
+ if (copy_name(vname_length, fullpath) != OK) {
+ /* Direct copy failed, try fetching from user space */
+ if (fetch_name(vname, vname_length, fullpath) != OK)
+ return(err_code);
+ }
if ((vp = eat_path(&resolve, fp)) == NULL) return(err_code);
} else { /* call_nr == FCHMOD */
/* File is already opened; get a pointer to vnode from filp. */
- if ((flp = get_filp(m_in.fd, VNODE_WRITE)) == NULL)
- return(err_code);
+ if ((flp = get_filp(rfd, VNODE_WRITE)) == NULL) return(err_code);
vp = flp->filp_vno;
dup_vnode(vp);
}
/* Now make the change. Clear setgid bit if file is not in caller's
* group */
if (fp->fp_effuid != SU_UID && vp->v_gid != fp->fp_effgid)
- m_in.mode &= ~I_SET_GID_BIT;
+ new_mode &= ~I_SET_GID_BIT;
- r = req_chmod(vp->v_fs_e, vp->v_inode_nr, m_in.mode, &new_mode);
+ r = req_chmod(vp->v_fs_e, vp->v_inode_nr, new_mode, &result_mode);
if (r == OK)
- vp->v_mode = new_mode;
+ vp->v_mode = result_mode;
}
- if (call_nr == CHMOD) {
+ if (job_call_nr == CHMOD) {
unlock_vnode(vp);
unlock_vmnt(vmp);
} else { /* FCHMOD */
struct filp *flp;
struct vnode *vp;
struct vmnt *vmp;
- int r;
- uid_t uid;
- gid_t gid;
+ int r, rfd;
+ uid_t uid, new_uid;
+ gid_t gid, new_gid;
mode_t new_mode;
char fullpath[PATH_MAX];
struct lookup resolve;
+ vir_bytes vname1;
+ size_t vname1_length;
flp = NULL;
+ vname1 = (vir_bytes) job_m_in.name1;
+ vname1_length = (size_t) job_m_in.name1_length;
+ rfd = job_m_in.fd;
+ uid = job_m_in.owner;
+ gid = job_m_in.group;
lookup_init(&resolve, fullpath, PATH_NOFLAGS, &vmp, &vp);
resolve.l_vmnt_lock = VMNT_WRITE;
resolve.l_vnode_lock = VNODE_WRITE;
- if (call_nr == CHOWN) {
+ if (job_call_nr == CHOWN) {
/* Temporarily open the file. */
- if (fetch_name(m_in.name1, m_in.name1_length, M1, fullpath) != OK)
+ if (fetch_name(vname1, vname1_length, fullpath) != OK)
return(err_code);
if ((vp = eat_path(&resolve, fp)) == NULL) return(err_code);
} else { /* call_nr == FCHOWN */
/* File is already opened; get a pointer to the vnode from filp. */
- if ((flp = get_filp(m_in.fd, VNODE_WRITE)) == NULL)
+ if ((flp = get_filp(rfd, VNODE_WRITE)) == NULL)
return(err_code);
vp = flp->filp_vno;
dup_vnode(vp);
if (fp->fp_effuid != SU_UID) {
/* Regular users can only change groups of their own files. */
if (vp->v_uid != fp->fp_effuid) r = EPERM;
- if (vp->v_uid != m_in.owner) r = EPERM; /* no giving away */
- if (fp->fp_effgid != m_in.group) r = EPERM;
+ if (vp->v_uid != uid) r = EPERM; /* no giving away */
+ if (fp->fp_effgid != gid) r = EPERM;
}
}
if (r == OK) {
/* Do not change uid/gid if new uid/gid is -1. */
- uid = (m_in.owner == (uid_t)-1 ? vp->v_uid : m_in.owner);
- gid = (m_in.group == (gid_t)-1 ? vp->v_gid : m_in.group);
+ new_uid = (uid == (uid_t)-1 ? vp->v_uid : uid);
+ new_gid = (gid == (gid_t)-1 ? vp->v_gid : gid);
- if (uid > UID_MAX || gid > GID_MAX)
+ if (new_uid > UID_MAX || new_gid > GID_MAX)
r = EINVAL;
- else if ((r = req_chown(vp->v_fs_e, vp->v_inode_nr, uid, gid,
+ else if ((r = req_chown(vp->v_fs_e, vp->v_inode_nr, new_uid, new_gid,
&new_mode)) == OK) {
- vp->v_uid = uid;
- vp->v_gid = gid;
+ vp->v_uid = new_uid;
+ vp->v_gid = new_gid;
vp->v_mode = new_mode;
}
}
- if (call_nr == CHOWN) {
+ if (job_call_nr == CHOWN) {
unlock_vnode(vp);
unlock_vmnt(vmp);
} else { /* FCHOWN */
int do_umask()
{
/* Perform the umask(co_mode) system call. */
- register mode_t r;
+ mode_t complement, new_umask;
+
+ new_umask = job_m_in.co_mode;
- r = ~fp->fp_umask; /* set 'r' to complement of old mask */
- fp->fp_umask = ~(m_in.co_mode & RWX_MODES);
- return(r); /* return complement of old mask */
+ complement = ~fp->fp_umask; /* set 'r' to complement of old mask */
+ fp->fp_umask = ~(new_umask & RWX_MODES);
+ return(complement); /* return complement of old mask */
}
*===========================================================================*/
int do_access()
{
-/* Perform the access(name, mode) system call. */
+/* Perform the access(name, mode) system call.
+ * syscall might provide 'name' embedded in the message.
+ */
int r;
struct vnode *vp;
struct vmnt *vmp;
char fullpath[PATH_MAX];
struct lookup resolve;
+ vir_bytes vname;
+ size_t vname_length;
+ mode_t access;
+
+ vname = (vir_bytes) job_m_in.name;
+ vname_length = (size_t) job_m_in.name_length;
+ access = job_m_in.mode;
lookup_init(&resolve, fullpath, PATH_NOFLAGS, &vmp, &vp);
resolve.l_vmnt_lock = VMNT_READ;
resolve.l_vnode_lock = VNODE_READ;
/* First check to see if the mode is correct. */
- if ( (m_in.mode & ~(R_OK | W_OK | X_OK)) != 0 && m_in.mode != F_OK)
+ if ( (access & ~(R_OK | W_OK | X_OK)) != 0 && access != F_OK)
return(EINVAL);
/* Temporarily open the file. */
- if (fetch_name(m_in.name, m_in.name_length, M3, fullpath) != OK)
- return(err_code);
+ if (copy_name(vname_length, fullpath) != OK) {
+ /* Direct copy failed, try fetching from user space */
+ if (fetch_name(vname, vname_length, fullpath) != OK)
+ return(err_code);
+ }
if ((vp = eat_path(&resolve, fp)) == NULL) return(err_code);
- r = forbidden(fp, vp, m_in.mode);
+ r = forbidden(fp, vp, access);
unlock_vnode(vp);
unlock_vmnt(vmp);
/* Isolate the relevant rwx bits from the mode. */
bits = vp->v_mode;
- uid = (call_nr == ACCESS ? rfp->fp_realuid : rfp->fp_effuid);
- gid = (call_nr == ACCESS ? rfp->fp_realgid : rfp->fp_effgid);
+ uid = (job_call_nr == ACCESS ? rfp->fp_realuid : rfp->fp_effuid);
+ gid = (job_call_nr == ACCESS ? rfp->fp_realgid : rfp->fp_effgid);
if (uid == SU_UID) {
/* Grant read and write permission. Grant search permission for
int clone_opcl(int op, dev_t dev, int proc, int flags);
int ctty_io(int task_nr, message *mess_ptr);
int do_ioctl(void);
-void pm_setsid(int proc_e);
-void dev_status(message *);
+void pm_setsid(endpoint_t proc_e);
+void dev_status(message *m);
void bdev_up(int major);
void cdev_up(int major);
endpoint_t find_suspended_ep(endpoint_t driver, cp_grant_id_t g);
void write_elf_core_file(struct filp *f, int csig, char *exe_name);
/* exec.c */
-int pm_exec(int proc_e, char *path, vir_bytes path_len, char *frame,
- vir_bytes frame_len, vir_bytes *pc);
+int pm_exec(int proc_e, vir_bytes path, size_t path_len, vir_bytes frame,
+ size_t frame_len, vir_bytes *pc);
#define check_bsf_lock() do { \
assert(mutex_trylock(&bsf_lock) == 0); \
unlock_bsf(); \
/* main.c */
int main(void);
-void reply(int whom, int result);
+void reply(endpoint_t whom, int result);
void lock_proc(struct fproc *rfp, int force_lock);
void unlock_proc(struct fproc *rfp);
void *do_dummy(void *arg);
/* pipe.c */
int do_pipe(void);
int map_vnode(struct vnode *vp, endpoint_t fs_e);
-void unpause(int proc_nr_e);
+void unpause(endpoint_t proc_e);
int pipe_check(struct vnode *vp, int rw_flag, int oflags, int bytes,
u64_t position, int notouch);
-void release(struct vnode *vp, int call_nr, int count);
-void revive(int proc_nr, int bytes);
-void suspend(int task);
+void release(struct vnode *vp, int op, int count);
+void revive(endpoint_t proc_e, int returned);
+void suspend(int why);
void pipe_suspend(struct filp *rfilp, char *buf, size_t size);
-void unsuspend_by_endpt(endpoint_t);
-void wait_for(endpoint_t);
-#if DO_SANITYCHECKS
-int check_pipe(void);
-#endif
+void unsuspend_by_endpt(endpoint_t proc_e);
+void wait_for(endpoint_t proc_e);
/* protect.c */
int do_access(void);
size_t req_size);
/* request.c */
-int req_breadwrite(endpoint_t fs_e, endpoint_t user_e, dev_t dev, u64_t
- pos, unsigned int num_of_bytes, char *user_addr, int rw_flag, u64_t
- *new_posp, unsigned int *cum_iop);
-int req_chmod(int fs_e, ino_t inode_nr, mode_t rmode, mode_t
- *new_modep);
-int req_chown(endpoint_t fs_e, ino_t inode_nr, uid_t newuid, gid_t
- newgid, mode_t *new_modep);
-int req_create(int fs_e, ino_t inode_nr, int omode, uid_t uid, gid_t
- gid, char *path, node_details_t *res);
+int req_breadwrite(endpoint_t fs_e, endpoint_t user_e, dev_t dev, u64_t pos,
+ unsigned int num_of_bytes, char *user_addr, int rw_flag,
+ u64_t *new_posp, unsigned int *cum_iop);
+int req_chmod(int fs_e, ino_t inode_nr, mode_t rmode, mode_t *new_modep);
+int req_chown(endpoint_t fs_e, ino_t inode_nr, uid_t newuid, gid_t newgid,
+ mode_t *new_modep);
+int req_create(int fs_e, ino_t inode_nr, int omode, uid_t uid, gid_t gid,
+ char *path, node_details_t *res);
int req_flush(endpoint_t fs_e, dev_t dev);
-int req_fstatfs(int fs_e, int who_e, char *buf);
-int req_statvfs(int fs_e, int who_e, char *buf);
+int req_fstatfs(endpoint_t fs_e, endpoint_t proc_e, vir_bytes buf);
+int req_statvfs(endpoint_t fs_e, endpoint_t proc_e, vir_bytes buf);
int req_ftrunc(endpoint_t fs_e, ino_t inode_nr, off_t start, off_t end);
int req_getdents(endpoint_t fs_e, ino_t inode_nr, u64_t pos, char *buf,
size_t size, u64_t *new_pos, int direct);
int req_inhibread(endpoint_t fs_e, ino_t inode_nr);
-int req_link(endpoint_t fs_e, ino_t link_parent, char *lastc, ino_t
- linked_file);
-int req_lookup(endpoint_t fs_e, ino_t dir_ino, ino_t root_ino, uid_t
- uid, gid_t gid, struct lookup *resolve, lookup_res_t *res, struct fproc
- *rfp);
+int req_link(endpoint_t fs_e, ino_t link_parent, char *lastc,
+ ino_t linked_file);
+int req_lookup(endpoint_t fs_e, ino_t dir_ino, ino_t root_ino, uid_t uid,
+ gid_t gid, struct lookup *resolve, lookup_res_t *res,
+ struct fproc *rfp);
int req_mkdir(endpoint_t fs_e, ino_t inode_nr, char *lastc, uid_t uid,
gid_t gid, mode_t dmode);
int req_mknod(endpoint_t fs_e, ino_t inode_nr, char *lastc, uid_t uid,
gid_t gid, mode_t dmode, dev_t dev);
int req_mountpoint(endpoint_t fs_e, ino_t inode_nr);
-int req_newnode(endpoint_t fs_e, uid_t uid, gid_t gid, mode_t dmode,
- dev_t dev, struct node_details *res);
+int req_newnode(endpoint_t fs_e, uid_t uid, gid_t gid, mode_t dmode, dev_t dev,
+ struct node_details *res);
int req_putnode(int fs_e, ino_t inode_nr, int count);
-int req_rdlink(endpoint_t fs_e, ino_t inode_nr, endpoint_t who_e, char
- *buf, size_t len, int direct);
-int req_readsuper(endpoint_t fs_e, char *driver_name, dev_t dev, int
- readonly, int isroot, struct node_details *res_nodep, int *con_reqs);
-int req_readwrite(endpoint_t fs_e, ino_t inode_nr, u64_t pos, int
- rw_flag, endpoint_t user_e, char *user_addr, unsigned int num_of_bytes,
+int req_rdlink(endpoint_t fs_e, ino_t inode_nr, endpoint_t proc_e,
+ vir_bytes buf, size_t len, int direct);
+int req_readsuper(endpoint_t fs_e, char *driver_name, dev_t dev, int readonly,
+ int isroot, struct node_details *res_nodep, int *con_reqs);
+int req_readwrite(endpoint_t fs_e, ino_t inode_nr, u64_t pos, int rw_flag,
+ endpoint_t user_e, char *user_addr, unsigned int num_of_bytes,
u64_t *new_posp, unsigned int *cum_iop);
-int req_rename(endpoint_t fs_e, ino_t old_dir, char *old_name, ino_t
- new_dir, char *new_name);
+int req_rename(endpoint_t fs_e, ino_t old_dir, char *old_name, ino_t new_dir,
+ char *new_name);
int req_rmdir(endpoint_t fs_e, ino_t inode_nr, char *lastc);
-int req_slink(endpoint_t fs_e, ino_t inode_nr, char *lastc, endpoint_t
- who_e, char *path_addr, unsigned short path_length, uid_t uid, gid_t
- gid);
-int req_stat(int fs_e, ino_t inode_nr, int who_e, char *buf, int pos,
- int stat_version);
+int req_slink(endpoint_t fs_e, ino_t inode_nr, char *lastc, endpoint_t proc_e,
+ vir_bytes path_addr, size_t path_length, uid_t uid, gid_t gid);
+int req_stat(endpoint_t fs_e, ino_t inode_nr, endpoint_t proc_e, vir_bytes buf,
+ int pos, int stat_version);
int req_sync(endpoint_t fs_e);
int req_unlink(endpoint_t fs_e, ino_t inode_nr, char *lastc);
int req_unmount(endpoint_t fs_e);
-int req_utime(endpoint_t fs_e, ino_t inode_nr, time_t actime, time_t
- modtime);
+int req_utime(endpoint_t fs_e, ino_t inode_nr, time_t actime, time_t modtime);
int req_newdriver(endpoint_t fs_e, dev_t dev, char *label);
/* stadir.c */
time_t clock_time(void);
unsigned conv2(int norm, int w);
long conv4(int norm, long x);
-int fetch_name(char *path, int len, int flag, char *dest);
+int copy_name(size_t len, char *dest);
+int fetch_name(vir_bytes path, size_t len, char *dest);
int no_sys(void);
int isokendpt_f(char *f, int l, endpoint_t e, int *p, int ft);
int in_group(struct fproc *rfp, gid_t grp);
void dup_vnode(struct vnode *vp);
void put_vnode(struct vnode *vp);
void vnode_clean_refs(struct vnode *vp);
-#if DO_SANITYCHECKS
-int check_vrefs(void);
-#endif
/* write.c */
int do_write(void);
struct worker_thread *worker_get(thread_t worker_tid);
struct job *worker_getjob(thread_t worker_tid);
void worker_init(struct worker_thread *worker);
-struct worker_thread *worker_self(void);
void worker_signal(struct worker_thread *worker);
void worker_start(void *(*func)(void *arg));
void worker_stop(struct worker_thread *worker);
*===========================================================================*/
void lock_bsf(void)
{
- message org_m_in;
struct fproc *org_fp;
struct worker_thread *org_self;
if (mutex_trylock(&bsf_lock) == 0)
return;
- org_m_in = m_in;
org_fp = fp;
org_self = self;
if (mutex_lock(&bsf_lock) != 0)
panic("unable to lock block special file lock");
- m_in = org_m_in;
fp = org_fp;
self = org_self;
}
tll_access_t locktype;
int r;
- scratch(fp).file.fd_nr = m_in.fd;
- scratch(fp).io.io_buffer = m_in.buffer;
- scratch(fp).io.io_nbytes = (size_t) m_in.nbytes;
+ scratch(fp).file.fd_nr = job_m_in.fd;
+ scratch(fp).io.io_buffer = job_m_in.buffer;
+ scratch(fp).io.io_nbytes = (size_t) job_m_in.nbytes;
locktype = (rw_flag == READING) ? VNODE_READ : VNODE_WRITE;
if ((f = get_filp(scratch(fp).file.fd_nr, locktype)) == NULL)
u64_t new_pos;
register struct filp *rfilp;
+ scratch(fp).file.fd_nr = job_m_in.fd;
+ scratch(fp).io.io_buffer = job_m_in.buffer;
+ scratch(fp).io.io_nbytes = (size_t) job_m_in.nbytes;
+
/* Is the file descriptor valid? */
- if ( (rfilp = get_filp(m_in.fd, VNODE_READ)) == NULL) return(err_code);
+ if ( (rfilp = get_filp(scratch(fp).file.fd_nr, VNODE_READ)) == NULL)
+ return(err_code);
if (!(rfilp->filp_mode & R_BIT))
r = EBADF;
panic("do_getdents: can't handle large offsets");
r = req_getdents(rfilp->filp_vno->v_fs_e, rfilp->filp_vno->v_inode_nr,
- rfilp->filp_pos, m_in.buffer, m_in.nbytes,&new_pos,0);
+ rfilp->filp_pos, scratch(fp).io.io_buffer,
+ scratch(fp).io.io_nbytes, &new_pos,0);
if (r > 0) rfilp->filp_pos = new_pos;
}
/*===========================================================================*
* req_fstatfs *
*===========================================================================*/
-int req_fstatfs(int fs_e, int proc_e, char *buf)
+int req_fstatfs(endpoint_t fs_e, endpoint_t proc_e, vir_bytes buf)
{
int r;
cp_grant_id_t grant_id;
message m;
- grant_id = cpf_grant_magic(fs_e, proc_e, (vir_bytes) buf, sizeof(struct statfs),
- CPF_WRITE);
- if(grant_id == -1)
- panic("req_fstatfs: cpf_grant_magic failed");
+ grant_id = cpf_grant_magic(fs_e, proc_e, buf, sizeof(struct statfs),
+ CPF_WRITE);
+ if (grant_id == GRANT_INVALID)
+ panic("req_fstatfs: cpf_grant_magic failed");
/* Fill in request message */
m.m_type = REQ_FSTATFS;
/*===========================================================================*
* req_statvfs *
*===========================================================================*/
-int req_statvfs(int fs_e, int proc_e, char *buf)
+int req_statvfs(endpoint_t fs_e, endpoint_t proc_e, vir_bytes buf)
{
int r;
cp_grant_id_t grant_id;
message m;
- grant_id = cpf_grant_magic(fs_e, proc_e, (vir_bytes) buf, sizeof(struct statvfs),
+ grant_id = cpf_grant_magic(fs_e, proc_e, buf, sizeof(struct statvfs),
CPF_WRITE);
- if(grant_id == -1)
- panic("req_statvfs: cpf_grant_magic failed");
+ if(grant_id == GRANT_INVALID)
+ panic("req_statvfs: cpf_grant_magic failed");
/* Fill in request message */
m.m_type = REQ_STATVFS;
endpoint_t fs_e;
ino_t inode_nr;
endpoint_t proc_e;
-char *buf;
+vir_bytes buf;
size_t len;
int direct; /* set to 1 to use direct grants instead of magic grants */
{
cp_grant_id_t grant_id;
if (direct) {
- grant_id = cpf_grant_direct(fs_e, (vir_bytes) buf, len, CPF_WRITE);
+ grant_id = cpf_grant_direct(fs_e, buf, len, CPF_WRITE);
} else {
- grant_id = cpf_grant_magic(fs_e, proc_e, (vir_bytes) buf, len,
- CPF_WRITE);
+ grant_id = cpf_grant_magic(fs_e, proc_e, buf, len, CPF_WRITE);
}
- if(grant_id == -1)
+ if (grant_id == -1)
panic("req_rdlink: cpf_grant_magic failed");
/* Fill in request message */
r = fs_sendrec(fs_e, &m);
cpf_revoke(grant_id);
- if(r == OK) r = m.RES_NBYTES;
+ if (r == OK) r = m.RES_NBYTES;
return(r);
}
ino_t inode_nr,
char *lastc,
endpoint_t proc_e,
- char *path_addr,
- unsigned short path_length,
+ vir_bytes path_addr,
+ size_t path_length,
uid_t uid,
gid_t gid
)
len = strlen(lastc) + 1;
gid_name = cpf_grant_direct(fs_e, (vir_bytes) lastc, len, CPF_READ);
- if(gid_name == -1)
+ if (gid_name == GRANT_INVALID)
panic("req_slink: cpf_grant_direct failed");
- gid_buf = cpf_grant_magic(fs_e, proc_e, (vir_bytes) path_addr, path_length,
- CPF_READ);
- if(gid_buf == -1) {
+ gid_buf = cpf_grant_magic(fs_e, proc_e, path_addr, path_length, CPF_READ);
+ if (gid_buf == GRANT_INVALID) {
cpf_revoke(gid_name);
panic("req_slink: cpf_grant_magic failed");
}
/*===========================================================================*
* req_stat *
*===========================================================================*/
-int req_stat(fs_e, inode_nr, proc_e, buf, pos, stat_version)
-int fs_e;
-ino_t inode_nr;
-int proc_e;
-char *buf;
-int pos;
-int stat_version;
+int req_stat(endpoint_t fs_e, ino_t inode_nr, endpoint_t proc_e, vir_bytes buf,
+ int pos, int stat_version)
{
cp_grant_id_t grant_id;
int r;
grant_id = cpf_grant_direct(fs_e, (vir_bytes) &sb,
sizeof(struct stat), CPF_WRITE);
else
- grant_id = cpf_grant_magic(fs_e, proc_e, (vir_bytes) buf,
- sizeof(struct stat), CPF_WRITE);
+ grant_id = cpf_grant_magic(fs_e, proc_e, buf, sizeof(struct stat),
+ CPF_WRITE);
if (grant_id < 0)
panic("req_stat: cpf_grant_* failed");
if (pos != 0)
sb.st_size -= pos;
if (stat_version == 0) {
- r = sys_vircopy(SELF, D, (vir_bytes) &sb, proc_e, D, (vir_bytes) buf,
+ r = sys_vircopy(SELF, D, (vir_bytes) &sb, proc_e, D, buf,
sizeof(struct stat));
return(r);
}
old_sb.st_ctime = sb.st_ctime;
#endif
- r = sys_vircopy(SELF, D, (vir_bytes) &old_sb, proc_e, D, (vir_bytes) buf,
+ r = sys_vircopy(SELF, D, (vir_bytes) &old_sb, proc_e, D, buf,
sizeof(struct minix_prev_stat));
return(r);
#define SEL_MAJORS (sizeof(select_majors) / sizeof(select_majors[0]))
/*===========================================================================*
- * do_select *
+ * do_select *
*===========================================================================*/
int do_select(void)
{
int r, nfds, do_timeout = 0, fd, s;
struct timeval timeout;
struct selectentry *se;
+ vir_bytes vtimeout;
- nfds = m_in.SEL_NFDS;
+ nfds = job_m_in.SEL_NFDS;
+ vtimeout = (vir_bytes) job_m_in.SEL_TIMEOUT;
/* Sane amount of file descriptors? */
if (nfds < 0 || nfds > OPEN_MAX) return(EINVAL);
se = &selecttab[s];
wipe_select(se); /* Clear results of previous usage */
se->req_endpt = who_e;
- se->vir_readfds = (fd_set *) m_in.SEL_READFDS;
- se->vir_writefds = (fd_set *) m_in.SEL_WRITEFDS;
- se->vir_errorfds = (fd_set *) m_in.SEL_ERRORFDS;
+ se->vir_readfds = (fd_set *) job_m_in.SEL_READFDS;
+ se->vir_writefds = (fd_set *) job_m_in.SEL_WRITEFDS;
+ se->vir_errorfds = (fd_set *) job_m_in.SEL_ERRORFDS;
/* Copy fdsets from the process */
if ((r = copy_fdsets(se, nfds, FROM_PROC)) != OK) return(r);
/* Did the process set a timeout value? If so, retrieve it. */
- if (m_in.SEL_TIMEOUT != NULL) {
+ if (vtimeout != 0) {
do_timeout = 1;
- r = sys_vircopy(who_e, D, (vir_bytes) m_in.SEL_TIMEOUT, SELF, D,
+ r = sys_vircopy(who_e, D, (vir_bytes) vtimeout, SELF, D,
(vir_bytes) &timeout, sizeof(timeout));
if (r != OK) return(r);
}
}
/*===========================================================================*
- * is_supported_major *
+ * is_supported_major *
*===========================================================================*/
static int is_supported_major(struct filp *f)
{
/* Find vnode and check we got a reply from the device we expected */
vp = f->filp_vno;
assert(vp != NULL);
- assert((vp->v_mode & I_TYPE) == I_CHAR_SPECIAL); /* Must be char. special */
+ assert((vp->v_mode & I_TYPE) == I_CHAR_SPECIAL);
if (vp->v_sdev != dev) {
printf("VFS (%s:%d): expected reply from dev %d not %d\n",
__FILE__, __LINE__, vp->v_sdev, dev);
}
/*===========================================================================*
- * select_lock_filp *
+ * select_lock_filp *
*===========================================================================*/
static void select_lock_filp(struct filp *f, int ops)
{
#include "vnode.h"
#include "vmnt.h"
-static int change(struct vnode **iip, char *name_ptr, int len);
static int change_into(struct vnode **iip, struct vnode *vp);
/*===========================================================================*
{
/* Change directory on already-opened fd. */
struct filp *rfilp;
- int r;
+ int r, rfd;
+
+ rfd = job_m_in.fd;
/* Is the file descriptor valid? */
- if ((rfilp = get_filp(m_in.fd, VNODE_READ)) == NULL) return(err_code);
+ if ((rfilp = get_filp(rfd, VNODE_READ)) == NULL) return(err_code);
r = change_into(&fp->fp_wd, rfilp->filp_vno);
unlock_filp(rfilp);
return(r);
*===========================================================================*/
int do_chdir()
{
-/* Perform the chdir(name) system call. */
+/* Perform the chdir(name) system call.
+ * syscall might provide 'name' embedded in the message.
+ */
- return change(&fp->fp_wd, m_in.name, m_in.name_length);
-}
+ int r;
+ struct vnode *vp;
+ struct vmnt *vmp;
+ char fullpath[PATH_MAX];
+ struct lookup resolve;
+ vir_bytes vname;
+ size_t vname_length;
-/*===========================================================================*
- * do_chroot *
- *===========================================================================*/
-int do_chroot()
-{
-/* Perform the chroot(name) system call. */
+ vname = (vir_bytes) job_m_in.name;
+ vname_length = (size_t) job_m_in.name_length;
- if (!super_user) return(EPERM); /* only su may chroot() */
- return change(&fp->fp_rd, m_in.name, m_in.name_length);
+ if (copy_name(vname_length, fullpath) != OK) {
+ /* Direct copy failed, try fetching from user space */
+ if (fetch_name(vname, vname_length, fullpath) != OK)
+ return(err_code);
+ }
+
+ /* Try to open the directory */
+ lookup_init(&resolve, fullpath, PATH_NOFLAGS, &vmp, &vp);
+ resolve.l_vmnt_lock = VMNT_READ;
+ resolve.l_vnode_lock = VNODE_READ;
+ if ((vp = eat_path(&resolve, fp)) == NULL) return(err_code);
+
+ r = change_into(&fp->fp_wd, vp);
+
+ unlock_vnode(vp);
+ unlock_vmnt(vmp);
+ put_vnode(vp);
+
+ return(r);
}
/*===========================================================================*
- * change *
+ * do_chroot *
*===========================================================================*/
-static int change(iip, name_ptr, len)
-struct vnode **iip; /* pointer to the inode pointer for the dir */
-char *name_ptr; /* pointer to the directory name to change to */
-int len; /* length of the directory name string */
+int do_chroot()
{
-/* Do the actual work for chdir() and chroot(). */
+/* Perform the chroot(name) system call.
+ * syscall might provide 'name' embedded in the message.
+ */
+ int r;
struct vnode *vp;
struct vmnt *vmp;
char fullpath[PATH_MAX];
struct lookup resolve;
- int r;
+ vir_bytes vname;
+ size_t vname_length;
+
+ vname = (vir_bytes) job_m_in.name;
+ vname_length = (size_t) job_m_in.name_length;
+
+ if (!super_user) return(EPERM); /* only su may chroot() */
+
+ if (copy_name(vname_length, fullpath) != OK) {
+ /* Direct copy failed, try fetching from user space */
+ if (fetch_name(vname, vname_length, fullpath) != OK)
+ return(err_code);
+ }
+ /* Try to open the directory */
lookup_init(&resolve, fullpath, PATH_NOFLAGS, &vmp, &vp);
resolve.l_vmnt_lock = VMNT_READ;
resolve.l_vnode_lock = VNODE_READ;
-
- /* Try to open the directory */
- if (fetch_name(name_ptr, len, M3, fullpath) != OK) return(err_code);
if ((vp = eat_path(&resolve, fp)) == NULL) return(err_code);
- r = change_into(iip, vp);
+
+ r = change_into(&fp->fp_rd, vp);
+
unlock_vnode(vp);
unlock_vmnt(vmp);
put_vnode(vp);
+
return(r);
}
/*===========================================================================*
* change_into *
*===========================================================================*/
-static int change_into(iip, vp)
-struct vnode **iip; /* pointer to the inode pointer for the dir */
-struct vnode *vp; /* this is what the inode has to become */
+static int change_into(struct vnode **result, struct vnode *vp)
{
int r;
- if (*iip == vp) return(OK); /* Nothing to do */
+ if (*result == vp) return(OK); /* Nothing to do */
/* It must be a directory and also be searchable */
if ((vp->v_mode & I_TYPE) != I_DIRECTORY)
if (r != OK) return(r);
/* Everything is OK. Make the change. */
- put_vnode(*iip); /* release the old directory */
+ put_vnode(*result); /* release the old directory */
dup_vnode(vp);
- *iip = vp; /* acquire the new one */
+ *result = vp; /* acquire the new one */
return(OK);
}
char fullpath[PATH_MAX];
struct lookup resolve;
int old_stat = 0;
+ vir_bytes vname1, statbuf;
+ size_t vname1_length;
+
+ vname1 = (vir_bytes) job_m_in.name1;
+ vname1_length = (size_t) job_m_in.name1_length;
+ statbuf = (vir_bytes) job_m_in.m1_p2;
lookup_init(&resolve, fullpath, PATH_NOFLAGS, &vmp, &vp);
resolve.l_vmnt_lock = VMNT_READ;
resolve.l_vnode_lock = VNODE_READ;
- if (call_nr == PREV_STAT)
+ if (job_call_nr == PREV_STAT)
old_stat = 1;
- if (fetch_name(m_in.name1, m_in.name1_length, M1, fullpath) != OK)
- return(err_code);
+ if (fetch_name(vname1, vname1_length, fullpath) != OK) return(err_code);
if ((vp = eat_path(&resolve, fp)) == NULL) return(err_code);
- r = req_stat(vp->v_fs_e, vp->v_inode_nr, who_e, m_in.name2, 0, old_stat);
+ r = req_stat(vp->v_fs_e, vp->v_inode_nr, who_e, statbuf, 0, old_stat);
unlock_vnode(vp);
unlock_vmnt(vmp);
{
/* Perform the fstat(fd, buf) system call. */
register struct filp *rfilp;
- int r;
- int pipe_pos = 0;
- int old_stat = 0;
+ int r, pipe_pos = 0, old_stat = 0, rfd;
+ vir_bytes statbuf;
+
+ statbuf = (vir_bytes) job_m_in.buffer;
+ rfd = job_m_in.fd;
- if (call_nr == PREV_FSTAT)
+ if (job_call_nr == PREV_FSTAT)
old_stat = 1;
/* Is the file descriptor valid? */
- if ((rfilp = get_filp(m_in.fd, VNODE_READ)) == NULL) return(err_code);
+ if ((rfilp = get_filp(rfd, VNODE_READ)) == NULL) return(err_code);
/* If we read from a pipe, send position too */
if (rfilp->filp_vno->v_pipe == I_PIPE) {
}
r = req_stat(rfilp->filp_vno->v_fs_e, rfilp->filp_vno->v_inode_nr,
- who_e, m_in.buffer, pipe_pos, old_stat);
+ who_e, statbuf, pipe_pos, old_stat);
unlock_filp(rfilp);
{
/* Perform the fstatfs(fd, buf) system call. */
struct filp *rfilp;
- int r;
+ int r, rfd;
+ vir_bytes statbuf;
+
+ rfd = job_m_in.fd;
+ statbuf = (vir_bytes) job_m_in.buffer;
/* Is the file descriptor valid? */
- if( (rfilp = get_filp(m_in.fd, VNODE_READ)) == NULL) return(err_code);
+ if( (rfilp = get_filp(rfd, VNODE_READ)) == NULL) return(err_code);
- r = req_fstatfs(rfilp->filp_vno->v_fs_e, who_e, m_in.buffer);
+ r = req_fstatfs(rfilp->filp_vno->v_fs_e, who_e, statbuf);
unlock_filp(rfilp);
}
/*===========================================================================*
- * do_statvfs *
+ * do_statvfs *
*===========================================================================*/
int do_statvfs()
{
struct vmnt *vmp;
char fullpath[PATH_MAX];
struct lookup resolve;
+ vir_bytes vname1, statbuf;
+ size_t vname1_length;
+
+ vname1 = (vir_bytes) job_m_in.name1;
+ vname1_length = (size_t) job_m_in.name1_length;
+ statbuf = (vir_bytes) job_m_in.name2;
lookup_init(&resolve, fullpath, PATH_NOFLAGS, &vmp, &vp);
resolve.l_vmnt_lock = VMNT_READ;
resolve.l_vnode_lock = VNODE_READ;
- if (fetch_name(m_in.STATVFS_NAME, m_in.STATVFS_LEN, M1, fullpath) != OK)
- return(err_code);
+ if (fetch_name(vname1, vname1_length, fullpath) != OK) return(err_code);
if ((vp = eat_path(&resolve, fp)) == NULL) return(err_code);
- r = req_statvfs(vp->v_fs_e, who_e, m_in.STATVFS_BUF);
+ r = req_statvfs(vp->v_fs_e, who_e, statbuf);
unlock_vnode(vp);
unlock_vmnt(vmp);
{
/* Perform the fstat(fd, buf) system call. */
register struct filp *rfilp;
- int r;
+ int r, rfd;
+ vir_bytes statbuf;
- /* Is the file descriptor valid? */
- if ((rfilp = get_filp(m_in.FSTATVFS_FD, VNODE_READ)) == NULL)
- return(err_code);
+ rfd = job_m_in.fd;
+ statbuf = (vir_bytes) job_m_in.name2;
- r = req_statvfs(rfilp->filp_vno->v_fs_e, who_e, m_in.FSTATVFS_BUF);
+ /* Is the file descriptor valid? */
+ if ((rfilp = get_filp(rfd, VNODE_READ)) == NULL) return(err_code);
+ r = req_statvfs(rfilp->filp_vno->v_fs_e, who_e, statbuf);
unlock_filp(rfilp);
char fullpath[PATH_MAX];
struct lookup resolve;
int old_stat = 0;
+ vir_bytes vname1, statbuf;
+ size_t vname1_length;
+
+ vname1 = (vir_bytes) job_m_in.name1;
+ vname1_length = (size_t) job_m_in.name1_length;
+ statbuf = (vir_bytes) job_m_in.name2;
lookup_init(&resolve, fullpath, PATH_RET_SYMLINK, &vmp, &vp);
resolve.l_vmnt_lock = VMNT_READ;
resolve.l_vnode_lock = VNODE_READ;
- if (call_nr == PREV_LSTAT)
+ if (job_call_nr == PREV_LSTAT)
old_stat = 1;
- if (fetch_name(m_in.name1, m_in.name1_length, M1, fullpath) != OK)
- return(err_code);
-
+ if (fetch_name(vname1, vname1_length, fullpath) != OK) return(err_code);
if ((vp = eat_path(&resolve, fp)) == NULL) return(err_code);
- r = req_stat(vp->v_fs_e, vp->v_inode_nr, who_e, m_in.name2, 0, old_stat);
+ r = req_stat(vp->v_fs_e, vp->v_inode_nr, who_e, statbuf, 0, old_stat);
unlock_vnode(vp);
unlock_vmnt(vmp);
int do_utime()
{
/* Perform the utime(name, timep) system call. */
- register int len;
int r;
- time_t actime, modtime;
+ time_t actime, modtime, newactime, newmodtime;
struct vnode *vp;
struct vmnt *vmp;
char fullpath[PATH_MAX];
struct lookup resolve;
+ vir_bytes vname;
+ size_t vname_length, len;
- lookup_init(&resolve, fullpath, PATH_NOFLAGS, &vmp, &vp);
- resolve.l_vmnt_lock = VMNT_WRITE;
- resolve.l_vnode_lock = VNODE_READ;
+ vname = (vir_bytes) job_m_in.utime_file;
+ vname_length = (size_t) job_m_in.utime_length;
+ actime = job_m_in.utime_actime;
+ modtime = job_m_in.utime_modtime;
/* Adjust for case of 'timep' being NULL;
* utime_strlen then holds the actual size: strlen(name)+1 */
- len = m_in.utime_length;
- if (len == 0) len = m_in.utime_strlen;
+ len = vname_length;
+ if (len == 0) len = (size_t) job_m_in.utime_strlen;
+
+ lookup_init(&resolve, fullpath, PATH_NOFLAGS, &vmp, &vp);
+ resolve.l_vmnt_lock = VMNT_WRITE;
+ resolve.l_vnode_lock = VNODE_READ;
/* Temporarily open the file */
- if (fetch_name(m_in.utime_file, len, M1, fullpath) != OK) return(err_code);
+ if (fetch_name(vname, len, fullpath) != OK) return(err_code);
if ((vp = eat_path(&resolve, fp)) == NULL) return(err_code);
/* Only the owner of a file or the super user can change its name. */
r = OK;
if (vp->v_uid != fp->fp_effuid && fp->fp_effuid != SU_UID) r = EPERM;
- if (m_in.utime_length == 0 && r != OK) r = forbidden(fp, vp, W_BIT);
+ if (vname_length == 0 && r != OK) r = forbidden(fp, vp, W_BIT);
if (read_only(vp) != OK) r = EROFS; /* Not even su can touch if R/O */
if (r == OK) {
/* Issue request */
- if(m_in.utime_length == 0) {
- actime = modtime = clock_time();
+ if (vname_length == 0) {
+ newactime = newmodtime = clock_time();
} else {
- actime = m_in.utime_actime;
- modtime = m_in.utime_modtime;
+ newactime = actime;
+ newmodtime = modtime;
}
- r = req_utime(vp->v_fs_e, vp->v_inode_nr, actime, modtime);
+ r = req_utime(vp->v_fs_e, vp->v_inode_nr, newactime, newmodtime);
}
unlock_vnode(vp);
#include "vmnt.h"
/*===========================================================================*
- * fetch_name *
+ * copy_name *
*===========================================================================*/
-int fetch_name(path, len, flag, dest)
-char *path; /* pointer to the path in user space */
-int len; /* path length, including 0 byte */
-int flag; /* M3 means path may be in message */
-char *dest; /* pointer to where path is to be stored */
+inline int copy_name( size_t len, char *dest)
{
-/* Go get path and put it in 'user_fullpath'.
- * If 'flag' = M3 and 'len' <= M3_STRING, the path is present in 'message'.
- * If it is not, go copy it from user space.
+/* Go get path and put it in 'dest'.
*/
register char *rpu, *rpm;
- int r, count;
if (len > PATH_MAX) { /* 'len' includes terminating-nul */
err_code = ENAMETOOLONG;
}
/* Check name length for validity. */
- if (len <= 0) {
+ if (len > SSIZE_MAX) {
err_code = EINVAL;
return(EGENERIC);
}
- if (flag == M3 && len <= M3_STRING) {
- /* Just copy the path from the message to 'user_fullpath'. */
+ if (len <= M3_STRING) {
+ /* Just copy the path from the message */
+ int count = 0;
rpu = &dest[0];
- rpm = m_in.pathname; /* contained in input message */
- count = len;
- do { *rpu++ = *rpm++; } while (--count);
- r = OK;
+ rpm = job_m_in.pathname; /* contained in input message */
+ for (count = 0; count <= len; count++)
+ *rpu++ = *rpm++;
} else {
- /* String is not contained in the message. Get it from user space. */
- r = sys_datacopy(who_e, (vir_bytes) path,
- VFS_PROC_NR, (vir_bytes) dest, (phys_bytes) len);
+ /* String is not contained in the message. */
+ err_code = EINVAL;
+ return(EGENERIC);
+ }
+
+ if (dest[len - 1] != '\0') {
+ err_code = ENAMETOOLONG;
+ return(EGENERIC);
+ }
+
+ return(OK);
+}
+
+/*===========================================================================*
+ * fetch_name *
+ *===========================================================================*/
+int fetch_name(vir_bytes path, size_t len, char *dest)
+{
+/* Go get path and put it in 'dest'. */
+ int r;
+
+ if (len > PATH_MAX) { /* 'len' includes terminating-nul */
+ err_code = ENAMETOOLONG;
+ return(EGENERIC);
+ }
+
+ /* Check name length for validity. */
+ if (len > SSIZE_MAX) {
+ err_code = EINVAL;
+ return(EGENERIC);
+ }
+
+ /* String is not contained in the message. Get it from user space. */
+ r = sys_datacopy(who_e, path, VFS_PROC_NR, (vir_bytes) dest, len);
+ if (r != OK) {
+ err_code = EINVAL;
+ return(r);
}
if (dest[len - 1] != '\0') {
return(EGENERIC);
}
- return(r);
+ return(OK);
}
/*===========================================================================*
* isokendpt_f *
*===========================================================================*/
-int isokendpt_f(char *file, int line, endpoint_t endpoint, int *proc, int fatal)
+int isokendpt_f(char *file, int line, endpoint_t endpoint, int *proc,
+ int fatal)
{
int failed = 0;
endpoint_t ke;
for (vmp = &vmnt[0]; vmp < &vmnt[NR_MNTS]; vmp++) {
if (tll_locked_by_me(&vmp->m_lock))
panic("Thread %d still holds vmnt lock on vmp %p call_nr=%d\n",
- mthread_self(), vmp, call_nr);
+ mthread_self(), vmp, job_call_nr);
}
if (rfp->fp_vmnt_rdlocks != 0)
panic("Thread %d still holds read locks on a vmnt (%d) call_nr=%d\n",
- mthread_self(), rfp->fp_vmnt_rdlocks, call_nr);
+ mthread_self(), rfp->fp_vmnt_rdlocks, job_call_nr);
}
#endif
for (vp = &vnode[0]; vp < &vnode[NR_VNODES]; vp++) {
if (tll_locked_by_me(&vp->v_lock)) {
panic("Thread %d still holds vnode lock on vp %x call_nr=%d\n",
- mthread_self(), vp, call_nr);
+ mthread_self(), vp, job_call_nr);
}
}
if (rfp->fp_vp_rdlocks != 0)
panic("Thread %d still holds read locks on a vnode (%d) call_nr=%d\n",
- mthread_self(), rfp->fp_vp_rdlocks, call_nr);
+ mthread_self(), rfp->fp_vp_rdlocks, job_call_nr);
}
#endif
vp->v_fs_count = 1;
}
-
-#define REFVP(v) { vp = (v); CHECKVN(v); vp->v_ref_check++; }
-
-#if DO_SANITYCHECKS
-/*===========================================================================*
- * check_vrefs *
- *===========================================================================*/
-int check_vrefs()
-{
- int i, bad;
- int ispipe_flag, ispipe_mode;
- struct vnode *vp;
- struct vmnt *vmp;
- struct fproc *rfp;
- struct filp *f;
-
- /* Clear v_ref_check */
- for (vp = &vnode[0]; vp < &vnode[NR_VNODES]; ++vp)
- vp->v_ref_check= 0;
-
- /* Count reference for processes */
- for (rfp=&fproc[0]; rfp < &fproc[NR_PROCS]; rfp++) {
- if (rfp->fp_pid == PID_FREE)
- continue;
- if(rfp->fp_rd) REFVP(rfp->fp_rd);
- if(rfp->fp_wd) REFVP(rfp->fp_wd);
- }
-
- /* Count references from filedescriptors */
- for (f = &filp[0]; f < &filp[NR_FILPS]; f++)
- {
- if (f->filp_count == 0)
- continue;
- REFVP(f->filp_vno);
- }
-
- /* Count references to mount points */
- for (vmp = &vmnt[0]; vmp < &vmnt[NR_MNTS]; ++vmp)
- {
- if (vmp->m_dev == NO_DEV)
- continue;
- REFVP(vmp->m_root_node);
- if(vmp->m_mounted_on)
- REFVP(vmp->m_mounted_on);
- }
-
- /* Check references */
- bad= 0;
- for (vp = &vnode[0]; vp < &vnode[NR_VNODES]; ++vp)
- {
- if (vp->v_ref_count != vp->v_ref_check)
- {
- printf(
-"Bad reference count for inode %d on device 0x%x: found %d, listed %d\n",
- vp->v_inode_nr, vp->v_dev, vp->v_ref_check,
- vp->v_ref_count);
- printf("last marked at %s, %d\n",
- vp->v_file, vp->v_line);
- bad= 1;
- }
-
- /* Also check v_pipe */
- if (vp->v_ref_count != 0)
- {
- ispipe_flag= (vp->v_pipe == I_PIPE);
- ispipe_mode= ((vp->v_mode & I_TYPE) == I_NAMED_PIPE);
- if (ispipe_flag != ispipe_mode)
- {
- printf(
-"Bad v_pipe for inode %d on device 0x%x: found %d, mode 0%o\n",
- vp->v_inode_nr, vp->v_dev, vp->v_pipe,
- vp->v_mode);
- printf("last marked at %s, %d\n",
- vp->v_file, vp->v_line);
- bad= 1;
- }
- }
- }
- return !bad;
-}
-#endif
panic("couldn't set default thread stack size");
if (mthread_attr_setdetachstate(&tattr, MTHREAD_CREATE_DETACHED) != 0)
panic("couldn't set default thread detach state");
+ invalid_thread_id = mthread_self(); /* Assuming we're the main thread*/
pending = 0;
init = 1;
}
/* Carry out work */
me->w_job.j_func(&me->w_job);
+ /* Deregister if possible */
+ if (me->w_job.j_fp != NULL) {
+ me->w_job.j_fp->fp_wtid = invalid_thread_id;
+ }
+
/* Mark ourselves as done */
me->w_job.j_func = NULL;
+ me->w_job.j_fp = NULL;
}
return(NULL); /* Unreachable */
*===========================================================================*/
void worker_wait(void)
{
- struct worker_thread *worker;
-
- worker = worker_self();
- worker->w_job.j_m_in = m_in; /* Store important global data */
- worker->w_job.j_err_code = err_code;
- assert(fp == worker->w_job.j_fp);
- worker_sleep(worker);
+ self->w_job.j_err_code = err_code;
+ assert(fp == self->w_job.j_fp);
+ worker_sleep(self);
/* We continue here after waking up */
- fp = worker->w_job.j_fp; /* Restore global data */
- m_in = worker->w_job.j_m_in;
- err_code = worker->w_job.j_err_code;
- assert(worker->w_next == NULL);
+ fp = self->w_job.j_fp; /* Restore global data */
+ err_code = self->w_job.j_err_code;
+ assert(self->w_next == NULL);
}
/*===========================================================================*
}
}
-/*===========================================================================*
- * worker_self *
- *===========================================================================*/
-struct worker_thread *worker_self(void)
-{
- struct worker_thread *worker;
- worker = worker_get(mthread_self());
- assert(worker != NULL);
- return(worker);
-}
-
/*===========================================================================*
* worker_get *
*===========================================================================*/