VFS: merge scratchpad into fproc

There is no reason to keep these tightly coupled data structures
separate.  Moreover, there is no reason to have a union of file
descriptor and file pointer, since the second can be derived from
the first.  The result are somewhat cleaner VFS internals.

Change-Id: I854da7d8291177878eecfc3077ef0a9e0cc82aaa
This commit is contained in:
David van Moolenbroek 2015-08-10 22:28:00 +00:00
parent 162f54c289
commit bd851af48f
12 changed files with 72 additions and 93 deletions

View file

@ -27,7 +27,6 @@
#include <minix/ioctl.h>
#include <minix/u64.h>
#include "file.h"
#include "scratchpad.h"
#include "dmap.h"
#include <minix/vfsif.h>
#include "vnode.h"
@ -357,9 +356,9 @@ static int cdev_clone(dev_t dev, devminor_t new_minor)
}
lock_vnode(vp, VNODE_OPCL);
assert(fp->fp_filp[scratch(fp).file.fd_nr] != NULL);
unlock_vnode(fp->fp_filp[scratch(fp).file.fd_nr]->filp_vno);
put_vnode(fp->fp_filp[scratch(fp).file.fd_nr]->filp_vno);
assert(fp->fp_filp[fp->fp_fd] != NULL);
unlock_vnode(fp->fp_filp[fp->fp_fd]->filp_vno);
put_vnode(fp->fp_filp[fp->fp_fd]->filp_vno);
vp->v_fs_e = res.fs_e;
vp->v_vmnt = NULL;
@ -370,7 +369,7 @@ static int cdev_clone(dev_t dev, devminor_t new_minor)
vp->v_sdev = dev;
vp->v_fs_count = 1;
vp->v_ref_count = 1;
fp->fp_filp[scratch(fp).file.fd_nr]->filp_vno = vp;
fp->fp_filp[fp->fp_fd]->filp_vno = vp;
return OK;
}
@ -513,11 +512,11 @@ int do_ioctl(void)
dev_t dev;
vir_bytes argx;
scratch(fp).file.fd_nr = job_m_in.m_lc_vfs_ioctl.fd;
fp->fp_fd = job_m_in.m_lc_vfs_ioctl.fd;
ioctlrequest = job_m_in.m_lc_vfs_ioctl.req;
argx = (vir_bytes)job_m_in.m_lc_vfs_ioctl.arg;
if ((f = get_filp(scratch(fp).file.fd_nr, VNODE_READ)) == NULL)
if ((f = get_filp(fp->fp_fd, VNODE_READ)) == NULL)
return(err_code);
vp = f->filp_vno; /* get vnode pointer */
if (!S_ISCHR(vp->v_mode) && !S_ISBLK(vp->v_mode)) {

View file

@ -31,6 +31,10 @@ EXTERN struct fproc {
endpoint_t fp_task; /* which task is proc suspended on */
cp_grant_id_t fp_grant; /* revoke this grant on unsuspend if > -1 */
int fp_fd; /* file descriptor for blocking call */
vir_bytes fp_io_buffer; /* user buffer address for ongoing I/O */
size_t fp_io_nbytes; /* number of bytes left for ongoing I/O */
uid_t fp_realuid; /* real user id */
uid_t fp_effuid; /* effective user id */
gid_t fp_realgid; /* real group id */

View file

@ -31,7 +31,6 @@ EXTERN message m_in; /* the input message itself */
# define job_m_out (self->w_m_out)
# 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 int deadlock_resolving;
EXTERN mutex_t bsf_lock;/* Global lock for access to block special files */

View file

@ -22,7 +22,6 @@
#include "file.h"
#include "path.h"
#include "vnode.h"
#include "scratchpad.h"
/*===========================================================================*
* do_link *
@ -333,13 +332,13 @@ int do_ftruncate(void)
int r;
off_t length;
scratch(fp).file.fd_nr = job_m_in.m_lc_vfs_truncate.fd;
fp->fp_fd = job_m_in.m_lc_vfs_truncate.fd;
length = job_m_in.m_lc_vfs_truncate.offset;
if (length < 0) return(EINVAL);
/* File is already opened; get a vnode pointer from filp */
if ((rfilp = get_filp(scratch(fp).file.fd_nr, VNODE_WRITE)) == NULL)
if ((rfilp = get_filp(fp->fp_fd, VNODE_WRITE)) == NULL)
return(err_code);
vp = rfilp->filp_vno;

View file

@ -11,7 +11,6 @@
#include <fcntl.h>
#include <unistd.h>
#include "file.h"
#include "scratchpad.h"
#include "lock.h"
#include "vnode.h"
@ -31,7 +30,7 @@ int req; /* either F_SETLK or F_SETLKW */
struct file_lock *flp, *flp2, *empty;
/* Fetch the flock structure from user space. */
r = sys_datacopy_wrapper(who_e, scratch(fp).io.io_buffer, VFS_PROC_NR,
r = sys_datacopy_wrapper(who_e, fp->fp_io_buffer, VFS_PROC_NR,
(vir_bytes) &flock, sizeof(flock));
if (r != OK) return(EINVAL);
@ -142,7 +141,7 @@ int req; /* either F_SETLK or F_SETLKW */
/* Copy the flock structure back to the caller. */
r = sys_datacopy_wrapper(VFS_PROC_NR, (vir_bytes) &flock, who_e,
scratch(fp).io.io_buffer, sizeof(flock));
fp->fp_io_buffer, sizeof(flock));
return(r);
}

View file

@ -26,7 +26,6 @@
#include <minix/debug.h>
#include <minix/vfsif.h>
#include "file.h"
#include "scratchpad.h"
#include "vmnt.h"
#include "vnode.h"
@ -211,15 +210,14 @@ static void do_pending_pipe(void)
struct filp *f;
tll_access_t locktype;
f = scratch(fp).file.filp;
f = fp->fp_filp[fp->fp_fd];
assert(f != NULL);
scratch(fp).file.filp = NULL;
locktype = (job_call_nr == VFS_READ) ? VNODE_READ : VNODE_WRITE;
op = (job_call_nr == VFS_READ) ? READING : WRITING;
lock_filp(f, locktype);
r = rw_pipe(op, who_e, f, scratch(fp).io.io_buffer, scratch(fp).io.io_nbytes);
r = rw_pipe(op, who_e, f, fp->fp_io_buffer, fp->fp_io_nbytes);
if (r != SUSPEND) { /* Do we have results to report? */
/* Process is writing, but there is no reader. Send a SIGPIPE signal.
@ -834,15 +832,15 @@ struct fproc *rfp;
case VFS_READ:
case VFS_WRITE:
assert(blocked_on == FP_BLOCKED_ON_PIPE);
m_in.m_lc_vfs_readwrite.fd = scratch(rfp).file.fd_nr;
m_in.m_lc_vfs_readwrite.buf = scratch(rfp).io.io_buffer;
m_in.m_lc_vfs_readwrite.len = scratch(rfp).io.io_nbytes;
m_in.m_lc_vfs_readwrite.fd = rfp->fp_fd;
m_in.m_lc_vfs_readwrite.buf = rfp->fp_io_buffer;
m_in.m_lc_vfs_readwrite.len = rfp->fp_io_nbytes;
break;
case VFS_FCNTL:
assert(blocked_on == FP_BLOCKED_ON_LOCK);
m_in.m_lc_vfs_fcntl.fd = scratch(rfp).file.fd_nr;
m_in.m_lc_vfs_fcntl.cmd = scratch(rfp).io.io_nbytes;
m_in.m_lc_vfs_fcntl.arg_ptr = scratch(rfp).io.io_buffer;
m_in.m_lc_vfs_fcntl.fd = rfp->fp_fd;
m_in.m_lc_vfs_fcntl.cmd = rfp->fp_io_nbytes;
m_in.m_lc_vfs_fcntl.arg_ptr = rfp->fp_io_buffer;
assert(m_in.m_lc_vfs_fcntl.cmd == F_SETLKW);
break;
default:

View file

@ -33,7 +33,6 @@
#include <sys/svrctl.h>
#include <sys/resource.h>
#include "file.h"
#include "scratchpad.h"
#include <minix/vfsif.h>
#include "vnode.h"
#include "vmnt.h"
@ -103,15 +102,15 @@ int do_fcntl(void)
int new_fd, fl, r = OK, fcntl_req, fcntl_argx;
tll_access_t locktype;
scratch(fp).file.fd_nr = job_m_in.m_lc_vfs_fcntl.fd;
scratch(fp).io.io_buffer = job_m_in.m_lc_vfs_fcntl.arg_ptr;
scratch(fp).io.io_nbytes = job_m_in.m_lc_vfs_fcntl.cmd;
fp->fp_fd = job_m_in.m_lc_vfs_fcntl.fd;
fp->fp_io_buffer = job_m_in.m_lc_vfs_fcntl.arg_ptr;
fp->fp_io_nbytes = job_m_in.m_lc_vfs_fcntl.cmd;
fcntl_req = job_m_in.m_lc_vfs_fcntl.cmd;
fcntl_argx = job_m_in.m_lc_vfs_fcntl.arg_int;
/* Is the file descriptor valid? */
locktype = (fcntl_req == F_FREESP) ? VNODE_WRITE : VNODE_READ;
if ((f = get_filp(scratch(fp).file.fd_nr, locktype)) == NULL)
if ((f = get_filp(fp->fp_fd, locktype)) == NULL)
return(err_code);
switch (fcntl_req) {
@ -132,16 +131,16 @@ int do_fcntl(void)
case F_GETFD:
/* Get close-on-exec flag (FD_CLOEXEC in POSIX Table 6-2). */
r = 0;
if (FD_ISSET(scratch(fp).file.fd_nr, &fp->fp_cloexec_set))
if (FD_ISSET(fp->fp_fd, &fp->fp_cloexec_set))
r = FD_CLOEXEC;
break;
case F_SETFD:
/* Set close-on-exec flag (FD_CLOEXEC in POSIX Table 6-2). */
if (fcntl_argx & FD_CLOEXEC)
FD_SET(scratch(fp).file.fd_nr, &fp->fp_cloexec_set);
FD_SET(fp->fp_fd, &fp->fp_cloexec_set);
else
FD_CLR(scratch(fp).file.fd_nr, &fp->fp_cloexec_set);
FD_CLR(fp->fp_fd, &fp->fp_cloexec_set);
break;
case F_GETFL:
@ -174,7 +173,7 @@ int do_fcntl(void)
else if (!(f->filp_mode & W_BIT)) r = EBADF;
else {
/* Copy flock data from userspace. */
r = sys_datacopy_wrapper(who_e, scratch(fp).io.io_buffer,
r = sys_datacopy_wrapper(who_e, fp->fp_io_buffer,
SELF, (vir_bytes) &flock_arg, sizeof(flock_arg));
}
@ -284,9 +283,9 @@ int do_fsync(void)
dev_t dev;
int r = OK;
scratch(fp).file.fd_nr = job_m_in.m_lc_vfs_fsync.fd;
fp->fp_fd = job_m_in.m_lc_vfs_fsync.fd;
if ((rfilp = get_filp(scratch(fp).file.fd_nr, VNODE_READ)) == NULL)
if ((rfilp = get_filp(fp->fp_fd, VNODE_READ)) == NULL)
return(err_code);
dev = rfilp->filp_vno->v_dev;
@ -885,8 +884,8 @@ int pm_dumpcore(int csig, vir_bytes exe_name)
char core_path[PATH_MAX];
char proc_name[PROC_NAME_LEN];
/* if a process is blocked, scratch(fp).file.fd_nr holds the fd it's blocked
* on. free it up for use by common_open().
/* if a process is blocked, fp->fp_fd holds the fd it's blocked on.
* free it up for use by common_open().
*/
if (fp_is_blocked(fp))
unpause();

View file

@ -18,7 +18,6 @@
#include <minix/com.h>
#include <minix/u64.h>
#include "file.h"
#include "scratchpad.h"
#include "lock.h"
#include <sys/dirent.h>
#include <assert.h>
@ -100,8 +99,7 @@ int common_open(char path[PATH_MAX], int oflags, mode_t omode)
if (!bits) return(EINVAL);
/* See if file descriptor and filp slots are available. */
if ((r = get_fd(fp, start, bits, &(scratch(fp).file.fd_nr),
&filp)) != OK)
if ((r = get_fd(fp, start, bits, &fp->fp_fd, &filp)) != OK)
return(r);
lookup_init(&resolve, path, PATH_NOFLAGS, &vmp, &vp);
@ -132,12 +130,12 @@ int common_open(char path[PATH_MAX], int oflags, mode_t omode)
}
/* Claim the file descriptor and filp slot and fill them in. */
fp->fp_filp[scratch(fp).file.fd_nr] = filp;
fp->fp_filp[fp->fp_fd] = filp;
filp->filp_count = 1;
filp->filp_vno = vp;
filp->filp_flags = oflags;
if (oflags & O_CLOEXEC)
FD_SET(scratch(fp).file.fd_nr, &fp->fp_cloexec_set);
FD_SET(fp->fp_fd, &fp->fp_cloexec_set);
/* Only do the normal open code if we didn't just create the file. */
if (exist) {
@ -243,7 +241,7 @@ int common_open(char path[PATH_MAX], int oflags, mode_t omode)
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;
fp->fp_filp[fp->fp_fd] = filp2;
filp2->filp_count++;
filp2->filp_vno = vp;
filp2->filp_flags = oflags;
@ -271,13 +269,13 @@ int common_open(char path[PATH_MAX], int oflags, mode_t omode)
/* If error, release inode. */
if (r != OK) {
if (r != SUSPEND) {
fp->fp_filp[scratch(fp).file.fd_nr] = NULL;
fp->fp_filp[fp->fp_fd] = NULL;
filp->filp_count = 0;
filp->filp_vno = NULL;
put_vnode(vp);
}
} else {
r = scratch(fp).file.fd_nr;
r = fp->fp_fd;
}
return(r);

View file

@ -27,7 +27,6 @@
#include <sys/select.h>
#include <sys/time.h>
#include "file.h"
#include "scratchpad.h"
#include <minix/vfsif.h>
#include "vnode.h"
#include "vmnt.h"
@ -334,9 +333,16 @@ size_t size;
* Store the parameters to be used upon resuming in the process table.
*/
scratch(fp).file.filp = filp;
scratch(fp).io.io_buffer = buf;
scratch(fp).io.io_nbytes = size;
/* We can only get here through an I/O call, which comes with a file
* descriptor, and that file descriptor must therefore correspond to the
* target file pointer of the I/O request. The process is blocked on the I/O
* call, and thus, the file descriptor will remain valid. Therefore, we can,
* and will, use the file descriptor to get the file pointer again later.
*/
assert(fp->fp_filp[fp->fp_fd] == filp);
fp->fp_io_buffer = buf;
fp->fp_io_nbytes = size;
suspend(FP_BLOCKED_ON_PIPE);
}
@ -409,17 +415,13 @@ int count; /* max number of processes to release */
*/
if (rp->fp_blocked_on == FP_BLOCKED_ON_POPEN ||
rp->fp_blocked_on == FP_BLOCKED_ON_PIPE ||
rp->fp_blocked_on == FP_BLOCKED_ON_LOCK ||
rp->fp_blocked_on == FP_BLOCKED_ON_OTHER) {
f = rp->fp_filp[scratch(rp).file.fd_nr];
f = rp->fp_filp[rp->fp_fd];
if (f == NULL || f->filp_mode == FILP_CLOSED)
continue;
if (rp->fp_filp[scratch(rp).file.fd_nr]->filp_vno != vp)
continue;
} else if (rp->fp_blocked_on == FP_BLOCKED_ON_PIPE) {
if (scratch(rp).file.filp == NULL)
continue;
if (scratch(rp).file.filp->filp_vno != vp)
if (f->filp_vno != vp)
continue;
} else
continue;
@ -459,14 +461,17 @@ void revive(endpoint_t proc_e, int returned)
* the proc must be restarted so it can try again.
*/
blocked_on = rfp->fp_blocked_on;
fd_nr = scratch(rfp).file.fd_nr;
fd_nr = rfp->fp_fd;
if (blocked_on == FP_BLOCKED_ON_PIPE || blocked_on == FP_BLOCKED_ON_LOCK) {
/* Revive a process suspended on a pipe or lock. */
rfp->fp_flags |= FP_REVIVED;
reviving++; /* process was waiting on pipe or lock */
} else {
rfp->fp_blocked_on = FP_BLOCKED_ON_NONE;
scratch(rfp).file.fd_nr = 0;
/* TODO: we could reset rfp->fp_fd to (e.g.) -1 here, but since its
* value is not always bounds checked elsewhere, this might do more
* harm than good right now.
*/
if (blocked_on == FP_BLOCKED_ON_POPEN) {
/* process blocked in open or create */
replycode(proc_e, fd_nr);
@ -476,7 +481,7 @@ void revive(endpoint_t proc_e, int returned)
/* Revive a process suspended on TTY or other device.
* Pretend it wants only what there is.
*/
scratch(rfp).io.io_nbytes = returned;
rfp->fp_io_nbytes = returned;
/* If a grant has been issued by FS for this I/O, revoke
* it again now that I/O is done.
*/
@ -545,7 +550,7 @@ void unpause(void)
break;
case FP_BLOCKED_ON_OTHER:/* process trying to do device I/O (e.g. tty)*/
fild = scratch(fp).file.fd_nr;
fild = fp->fp_fd;
if (fild < 0 || fild >= OPEN_MAX)
panic("file descriptor out-of-range");
f = fp->fp_filp[fild];

View file

@ -20,7 +20,6 @@
#include <fcntl.h>
#include <unistd.h>
#include "file.h"
#include "scratchpad.h"
#include "vnode.h"
#include "vmnt.h"
@ -92,12 +91,12 @@ int actual_read_write_peek(struct fproc *rfp, int rw_flag, int io_fd,
if(rw_flag == WRITING) ro = 0;
scratch(rfp).file.fd_nr = io_fd;
scratch(rfp).io.io_buffer = io_buf;
scratch(rfp).io.io_nbytes = io_nbytes;
rfp->fp_fd = io_fd;
rfp->fp_io_buffer = io_buf;
rfp->fp_io_nbytes = io_nbytes;
locktype = rw_flag == WRITING ? VNODE_WRITE : VNODE_READ;
if ((f = get_filp2(rfp, scratch(rfp).file.fd_nr, locktype)) == NULL)
if ((f = get_filp2(rfp, rfp->fp_fd, locktype)) == NULL)
return(err_code);
assert(f->filp_count > 0);
@ -106,13 +105,12 @@ int actual_read_write_peek(struct fproc *rfp, int rw_flag, int io_fd,
unlock_filp(f);
return(EBADF);
}
if (scratch(rfp).io.io_nbytes == 0) {
if (rfp->fp_io_nbytes == 0) {
unlock_filp(f);
return(0); /* so char special files need not check for 0*/
}
r = read_write(rfp, rw_flag, f, scratch(rfp).io.io_buffer,
scratch(rfp).io.io_nbytes, who_e);
r = read_write(rfp, rw_flag, f, rfp->fp_io_buffer, rfp->fp_io_nbytes, who_e);
unlock_filp(f);
return(r);
@ -274,12 +272,12 @@ int do_getdents(void)
off_t new_pos;
register struct filp *rfilp;
scratch(fp).file.fd_nr = job_m_in.m_lc_vfs_readwrite.fd;
scratch(fp).io.io_buffer = job_m_in.m_lc_vfs_readwrite.buf;
scratch(fp).io.io_nbytes = job_m_in.m_lc_vfs_readwrite.len;
fp->fp_fd = job_m_in.m_lc_vfs_readwrite.fd;
fp->fp_io_buffer = job_m_in.m_lc_vfs_readwrite.buf;
fp->fp_io_nbytes = job_m_in.m_lc_vfs_readwrite.len;
/* Is the file descriptor valid? */
if ( (rfilp = get_filp(scratch(fp).file.fd_nr, VNODE_READ)) == NULL)
if ( (rfilp = get_filp(fp->fp_fd, VNODE_READ)) == NULL)
return(err_code);
if (!(rfilp->filp_mode & R_BIT))
@ -289,8 +287,8 @@ int do_getdents(void)
if (r == OK) {
r = req_getdents(rfilp->filp_vno->v_fs_e, rfilp->filp_vno->v_inode_nr,
rfilp->filp_pos, scratch(fp).io.io_buffer,
scratch(fp).io.io_nbytes, &new_pos, 0);
rfilp->filp_pos, fp->fp_io_buffer, fp->fp_io_nbytes,
&new_pos, 0);
if (r > 0) rfilp->filp_pos = new_pos;
}

View file

@ -1,18 +0,0 @@
#ifndef __VFS_SCRATCHPAD_H__
#define __VFS_SCRATCHPAD_H__
/* This is the per-process information. A slot is reserved for each potential
* process. Thus NR_PROCS must be the same as in the kernel.
*/
EXTERN struct scratchpad {
union sp_data {
int fd_nr;
struct filp *filp;
} file;
struct io_cmd {
vir_bytes io_buffer;
size_t io_nbytes;
} io;
} scratchpad[NR_PROCS];
#endif

View file

@ -9,7 +9,6 @@
#include <minix/com.h>
#include "file.h"
#include "lock.h"
#include "scratchpad.h"
#include "vnode.h"
#include "vmnt.h"