VFS: remove support for sync char driver protocol

Change-Id: I57cc870a053b813b3a3fc45da46606ea84fe4cb1
This commit is contained in:
David van Moolenbroek 2013-08-30 13:33:56 +02:00 committed by Lionel Sambuc
parent c7fbafe1ad
commit 87aefd7eb2
8 changed files with 237 additions and 279 deletions

View file

@ -43,12 +43,4 @@
*/ */
#define FSTYPE_MAX VFS_NAMELEN /* maximum file system type size */ #define FSTYPE_MAX VFS_NAMELEN /* maximum file system type size */
/* Args to dev_io */
#define VFS_DEV_READ 2001
#define VFS_DEV_WRITE 2002
#define VFS_DEV_IOCTL 2005
#define VFS_DEV_SELECT 2006
#define dev_style_asyn(n) (TRUE)
#endif #endif

View file

@ -8,8 +8,8 @@
* bdev_open: open a block device * bdev_open: open a block device
* bdev_close: close a block device * bdev_close: close a block device
* dev_io: FS does a read or write on a device * dev_io: FS does a read or write on a device
* gen_opcl: generic call to a task to perform an open/close * gen_opcl: generic call to a character driver to perform an open/close
* gen_io: generic call to a task to perform an I/O operation * gen_io: generic call to a character driver to initiate I/O
* no_dev: open/close processing for devices that don't exist * no_dev: open/close processing for devices that don't exist
* no_dev_io: i/o processing for devices that don't exist * no_dev_io: i/o processing for devices that don't exist
* tty_opcl: perform tty-specific processing for open/close * tty_opcl: perform tty-specific processing for open/close
@ -17,6 +17,9 @@
* ctty_io: perform controlling-tty-specific processing for I/O * ctty_io: perform controlling-tty-specific processing for I/O
* pm_setsid: perform VFS's side of setsid system call * pm_setsid: perform VFS's side of setsid system call
* do_ioctl: perform the IOCTL system call * do_ioctl: perform the IOCTL system call
* task_reply: process the result of a character driver I/O request
* dev_select: initiate a select call on a device
* dev_cancel: cancel an I/O request, blocking until it has been cancelled
*/ */
#include "fs.h" #include "fs.h"
@ -38,9 +41,10 @@
#include "vmnt.h" #include "vmnt.h"
#include "param.h" #include "param.h"
static int block_io(endpoint_t driver_e, message *mess_ptr);
static cp_grant_id_t make_grant(endpoint_t driver_e, endpoint_t user_e, int op,
void *buf, size_t size);
static void restart_reopen(int major); static void restart_reopen(int major);
static int safe_io_conversion(endpoint_t, cp_grant_id_t *, int *,
endpoint_t *, void **, size_t, u32_t *);
static int dummyproc; static int dummyproc;
@ -157,10 +161,9 @@ static int bdev_ioctl(dev_t dev, endpoint_t proc_e, int req, void *buf)
{ {
/* Perform an I/O control operation on a block device. */ /* Perform an I/O control operation on a block device. */
struct dmap *dp; struct dmap *dp;
u32_t dummy;
cp_grant_id_t gid; cp_grant_id_t gid;
message dev_mess; message dev_mess;
int op, major_dev, minor_dev; int major_dev, minor_dev;
major_dev = major(dev); major_dev = major(dev);
minor_dev = minor(dev); minor_dev = minor(dev);
@ -173,9 +176,7 @@ static int bdev_ioctl(dev_t dev, endpoint_t proc_e, int req, void *buf)
} }
/* Set up a grant if necessary. */ /* Set up a grant if necessary. */
op = VFS_DEV_IOCTL; gid = make_grant(dp->dmap_driver, proc_e, BDEV_IOCTL, buf, req);
(void) safe_io_conversion(dp->dmap_driver, &gid, &op, &proc_e, &buf, req,
&dummy);
/* Set up the message passed to the task. */ /* Set up the message passed to the task. */
memset(&dev_mess, 0, sizeof(dev_mess)); memset(&dev_mess, 0, sizeof(dev_mess));
@ -187,7 +188,7 @@ static int bdev_ioctl(dev_t dev, endpoint_t proc_e, int req, void *buf)
dev_mess.BDEV_ID = 0; dev_mess.BDEV_ID = 0;
/* Call the task. */ /* Call the task. */
gen_io(dp->dmap_driver, &dev_mess); block_io(dp->dmap_driver, &dev_mess);
/* Clean up. */ /* Clean up. */
if (GRANT_VALID(gid)) cpf_revoke(gid); if (GRANT_VALID(gid)) cpf_revoke(gid);
@ -205,7 +206,7 @@ static int bdev_ioctl(dev_t dev, endpoint_t proc_e, int req, void *buf)
/*===========================================================================* /*===========================================================================*
* find_suspended_ep * * find_suspended_ep *
*===========================================================================*/ *===========================================================================*/
endpoint_t find_suspended_ep(endpoint_t driver, cp_grant_id_t g) static endpoint_t find_suspended_ep(endpoint_t driver, cp_grant_id_t g)
{ {
/* A process is suspended on a driver for which VFS issued a grant. Find out /* A process is suspended on a driver for which VFS issued a grant. Find out
* which process it was. * which process it was.
@ -215,50 +216,41 @@ endpoint_t find_suspended_ep(endpoint_t driver, cp_grant_id_t g)
if(rfp->fp_pid == PID_FREE) if(rfp->fp_pid == PID_FREE)
continue; continue;
if(rfp->fp_blocked_on == FP_BLOCKED_ON_OTHER && if (rfp->fp_task == driver && rfp->fp_grant == g) {
rfp->fp_task == driver && rfp->fp_grant == g) assert(!fp_is_blocked(rfp) ||
rfp->fp_blocked_on == FP_BLOCKED_ON_OTHER);
return(rfp->fp_endpoint); return(rfp->fp_endpoint);
} }
}
return(NONE); return(NONE);
} }
/*===========================================================================* /*===========================================================================*
* safe_io_conversion * * make_grant *
*===========================================================================*/ *===========================================================================*/
static int safe_io_conversion(driver, gid, op, io_ept, buf, bytes, pos_lo) static cp_grant_id_t make_grant(endpoint_t driver_e, endpoint_t user_e, int op,
endpoint_t driver; void *buf, size_t bytes)
cp_grant_id_t *gid;
int *op;
endpoint_t *io_ept;
void **buf;
size_t bytes;
u32_t *pos_lo;
{ {
/* Convert operation to the 'safe' variant (i.e., grant based) if applicable. /* Create a magic grant for the given operation and buffer. */
* If no copying of data is involved, there is also no need to convert. */ cp_grant_id_t gid;
int access;
int access = 0;
size_t size; size_t size;
*gid = GRANT_INVALID; /* Grant to buffer */ switch (op) {
case DEV_READ_S:
switch(*op) { case DEV_WRITE_S:
case VFS_DEV_READ: gid = cpf_grant_magic(driver_e, user_e, (vir_bytes) buf, bytes,
case VFS_DEV_WRITE: op == DEV_READ_S ? CPF_WRITE : CPF_READ);
/* Change to safe op. */
*op = (*op == VFS_DEV_READ) ? DEV_READ_S : DEV_WRITE_S;
*gid = cpf_grant_magic(driver, *io_ept, (vir_bytes) *buf, bytes,
*op == DEV_READ_S ? CPF_WRITE : CPF_READ);
if (*gid < 0)
panic("VFS: cpf_grant_magic of READ/WRITE buffer failed");
break; break;
case VFS_DEV_IOCTL:
*pos_lo = *io_ept; /* Old endpoint in POSITION field. */ case DEV_IOCTL_S:
*op = DEV_IOCTL_S; case BDEV_IOCTL:
/* For IOCTLs, the bytes parameter encodes requested access method /* For IOCTLs, the bytes parameter encodes requested access method
* and buffer size */ * and buffer size
*/
access = 0;
if(_MINIX_IOCTL_IOR(bytes)) access |= CPF_WRITE; if(_MINIX_IOCTL_IOR(bytes)) access |= CPF_WRITE;
if(_MINIX_IOCTL_IOW(bytes)) access |= CPF_READ; if(_MINIX_IOCTL_IOW(bytes)) access |= CPF_READ;
if(_MINIX_IOCTL_BIG(bytes)) if(_MINIX_IOCTL_BIG(bytes))
@ -269,37 +261,25 @@ u32_t *pos_lo;
/* Grant access to the buffer even if no I/O happens with the ioctl, in /* Grant access to the buffer even if no I/O happens with the ioctl, in
* order to disambiguate requests with DEV_IOCTL_S. * order to disambiguate requests with DEV_IOCTL_S.
*/ */
*gid = cpf_grant_magic(driver, *io_ept, (vir_bytes) *buf, size, access); gid = cpf_grant_magic(driver_e, user_e, (vir_bytes) buf, size, access);
if (*gid < 0) break;
panic("VFS: cpf_grant_magic IOCTL buffer failed");
break;
case VFS_DEV_SELECT:
*op = DEV_SELECT;
break;
default: default:
panic("VFS: unknown operation %d for safe I/O conversion", *op); panic("VFS: unknown operation %d", op);
} }
/* If we have converted to a safe operation, I/O endpoint becomes VFS if it if (!GRANT_VALID(gid))
* wasn't already. panic("VFS: cpf_grant_magic failed");
*/
if(GRANT_VALID(*gid)) { return gid;
*io_ept = VFS_PROC_NR;
return(1);
} }
/* Not converted to a safe operation (because there is no copying involved in
* this operation).
*/
return(0);
}
/*===========================================================================* /*===========================================================================*
* dev_io * * dev_io *
*===========================================================================*/ *===========================================================================*/
int dev_io( int dev_io(
int op, /* DEV_READ, DEV_WRITE, DEV_IOCTL, etc. */ int op, /* DEV_READ_S, DEV_WRITE_S, or DEV_IOCTL_S */
dev_t dev, /* major-minor device number */ dev_t dev, /* major-minor device number */
endpoint_t proc_e, /* in whose address space is buf? */ endpoint_t proc_e, /* in whose address space is buf? */
void *buf, /* virtual address of the buffer */ void *buf, /* virtual address of the buffer */
@ -309,22 +289,17 @@ int dev_io(
int suspend_reopen /* Just suspend the process */ int suspend_reopen /* Just suspend the process */
) )
{ {
/* Read from or write to a device. The parameter 'dev' tells which one. */ /* Initiate a read, write, or ioctl to a device. */
struct dmap *dp; struct dmap *dp;
u32_t pos_lo, pos_high;
message dev_mess; message dev_mess;
cp_grant_id_t gid = GRANT_INVALID; cp_grant_id_t gid;
int safe, minor_dev, major_dev; int r, minor_dev, major_dev;
void *buf_used;
endpoint_t ioproc;
int ret, is_asyn;
pos_lo = ex64lo(pos); assert(op == DEV_READ_S || op == DEV_WRITE_S || op == DEV_IOCTL_S);
pos_high = ex64hi(pos);
major_dev = major(dev);
minor_dev = minor(dev);
/* Determine task dmap. */ /* Determine task dmap. */
major_dev = major(dev);
minor_dev = minor(dev);
dp = &dmap[major_dev]; dp = &dmap[major_dev];
/* See if driver is roughly valid. */ /* See if driver is roughly valid. */
@ -345,77 +320,42 @@ int dev_io(
return(ENXIO); return(ENXIO);
} }
/* By default, these are right. */ /* Create a grant for the buffer provided by the user process. */
dev_mess.USER_ENDPT = proc_e; gid = make_grant(dp->dmap_driver, proc_e, op, buf, bytes);
dev_mess.ADDRESS = buf;
/* Convert DEV_* to DEV_*_S variants. */ /* Set up the rest of the message that will be sent to the driver. */
buf_used = buf;
safe = safe_io_conversion(dp->dmap_driver, &gid, &op,
(endpoint_t *) &dev_mess.USER_ENDPT, &buf_used,
bytes, &pos_lo);
is_asyn = dev_style_asyn(dp->dmap_style);
/* If the safe conversion was done, set the IO_GRANT to
* the grant id.
*/
if(safe) dev_mess.IO_GRANT = (char *) gid;
/* Set up the rest of the message passed to task. */
dev_mess.m_type = op; dev_mess.m_type = op;
dev_mess.DEVICE = minor_dev; dev_mess.DEVICE = minor_dev;
dev_mess.POSITION = pos_lo; if (op == DEV_IOCTL_S) {
dev_mess.REQUEST = bytes;
dev_mess.POSITION = proc_e;
} else {
dev_mess.POSITION = ex64lo(pos);
dev_mess.COUNT = bytes; dev_mess.COUNT = bytes;
dev_mess.HIGHPOS = pos_high; }
dev_mess.HIGHPOS = ex64hi(pos);
dev_mess.USER_ENDPT = VFS_PROC_NR;
dev_mess.IO_GRANT = (void *) gid;
dev_mess.FLAGS = 0; dev_mess.FLAGS = 0;
if (flags & O_NONBLOCK) if (flags & O_NONBLOCK)
dev_mess.FLAGS |= FLG_OP_NONBLOCK; dev_mess.FLAGS |= FLG_OP_NONBLOCK;
/* This will be used if the i/o is suspended. */ /* Send the request to the driver. */
ioproc = dev_mess.USER_ENDPT; r = (*dp->dmap_io)(dp->dmap_driver, &dev_mess);
/* Call the task. */ if (r != OK) {
(*dp->dmap_io)(dp->dmap_driver, &dev_mess); cpf_revoke(gid);
if(dp->dmap_driver == NONE) { return r;
/* Driver has vanished. */
printf("VFS: driver gone?!\n");
if(safe) cpf_revoke(gid);
return(EIO);
} }
ret = dev_mess.REP_STATUS; /* Suspend the calling process until a reply arrives. */
/* Legacy support: translate EINTR to EAGAIN for nonblocking calls. */
if (ret == EINTR && (flags & O_NONBLOCK))
ret = EAGAIN;
/* Task has completed. See if call completed. */
if (ret == SUSPEND) {
if ((flags & O_NONBLOCK) && !is_asyn) {
printf("VFS: sync char driver %u sent SUSPEND on NONBLOCK\n",
dp->dmap_driver);
/* We'd cancel, but the other side won't play ball anyway.. */
}
/* select() will do suspending itself. */
if(op != DEV_SELECT) {
/* Suspend user. */
wait_for(dp->dmap_driver); wait_for(dp->dmap_driver);
}
assert(!GRANT_VALID(fp->fp_grant)); assert(!GRANT_VALID(fp->fp_grant));
fp->fp_grant = gid; /* revoke this when unsuspended. */ fp->fp_grant = gid; /* revoke this when unsuspended. */
fp->fp_ioproc = ioproc; fp->fp_ioproc = VFS_PROC_NR;
return(SUSPEND); return SUSPEND;
}
/* No suspend, or cancelled suspend, so I/O is over and can be cleaned up. */
if(safe) cpf_revoke(gid);
return ret;
} }
/*===========================================================================* /*===========================================================================*
@ -450,7 +390,7 @@ int gen_opcl(
dev_mess.BDEV_ID = 0; dev_mess.BDEV_ID = 0;
/* Call the task. */ /* Call the task. */
r = gen_io(dp->dmap_driver, &dev_mess); r = block_io(dp->dmap_driver, &dev_mess);
} else { } else {
dev_mess.m_type = op; dev_mess.m_type = op;
dev_mess.DEVICE = minor_dev; dev_mess.DEVICE = minor_dev;
@ -463,7 +403,7 @@ int gen_opcl(
if (r != OK) return(r); if (r != OK) return(r);
if (op == DEV_OPEN && dev_style_asyn(dp->dmap_style)) { if (op == DEV_OPEN) {
fp->fp_task = dp->dmap_driver; fp->fp_task = dp->dmap_driver;
self->w_task = dp->dmap_driver; self->w_task = dp->dmap_driver;
self->w_drv_sendrec = &dev_mess; self->w_drv_sendrec = &dev_mess;
@ -593,7 +533,7 @@ int do_ioctl(message *UNUSED(m_out))
if (S_ISBLK(vp->v_mode)) if (S_ISBLK(vp->v_mode))
r = bdev_ioctl(dev, who_e, ioctlrequest, argx); r = bdev_ioctl(dev, who_e, ioctlrequest, argx);
else else
r = dev_io(VFS_DEV_IOCTL, dev, who_e, argx, 0, r = dev_io(DEV_IOCTL_S, dev, who_e, argx, 0,
ioctlrequest, f->filp_flags, suspend_reopen); ioctlrequest, f->filp_flags, suspend_reopen);
} }
@ -604,31 +544,100 @@ int do_ioctl(message *UNUSED(m_out))
/*===========================================================================* /*===========================================================================*
* gen_io * * dev_select *
*===========================================================================*/ *===========================================================================*/
int gen_io(driver_e, mess_ptr) int dev_select(dev_t dev, int ops)
endpoint_t driver_e; /* which endpoint to call */
message *mess_ptr; /* pointer to message for task */
{ {
/* All file system I/O ultimately comes down to I/O on major/minor device /* Initiate a select call on a device. Return OK iff the request was sent. */
* pairs. These lead to calls on the following routines via the dmap table. int major_dev, minor_dev;
message dev_mess;
struct dmap *dp;
major_dev = major(dev);
minor_dev = minor(dev);
dp = &dmap[major_dev];
if (dp->dmap_driver == NONE) return ENXIO;
memset(&dev_mess, 0, sizeof(dev_mess));
dev_mess.m_type = DEV_SELECT;
dev_mess.DEV_MINOR = minor_dev;
dev_mess.DEV_SEL_OPS = ops;
/* Call the task. */
return (*dp->dmap_io)(dp->dmap_driver, &dev_mess);
}
/*===========================================================================*
* dev_cancel *
*===========================================================================*/
int dev_cancel(dev_t dev)
{
/* Cancel an I/O request, blocking until it has been cancelled. */
int r, minor_dev, major_dev;
message dev_mess;
struct dmap *dp;
major_dev = major(dev);
minor_dev = minor(dev);
dp = &dmap[major_dev];
memset(&dev_mess, 0, sizeof(dev_mess));
dev_mess.m_type = CANCEL;
dev_mess.DEVICE = minor_dev;
dev_mess.USER_ENDPT = fp->fp_ioproc;
dev_mess.IO_GRANT = (char *) fp->fp_grant;
/* Tell driver R or W. Mode is from current call, not open. */
/* FIXME: ioctls also pass through here! */
dev_mess.COUNT = fp->fp_block_callnr == READ ? R_BIT : W_BIT;
r = (*dp->dmap_io)(fp->fp_task, &dev_mess);
if (r != OK) return r; /* ctty_io returned an error? should be impossible */
/* Suspend this thread until we have received the response. */
fp->fp_task = dp->dmap_driver;
self->w_task = dp->dmap_driver;
self->w_drv_sendrec = &dev_mess;
worker_wait();
self->w_task = NONE;
self->w_drv_sendrec = NULL;
/* Clean up and return the result (note: the request may have completed). */
if (GRANT_VALID(fp->fp_grant)) {
(void) cpf_revoke(fp->fp_grant);
fp->fp_grant = GRANT_INVALID;
}
r = dev_mess.REP_STATUS;
return (r == EAGAIN) ? EINTR : r;
}
/*===========================================================================*
* block_io *
*===========================================================================*/
static int block_io(endpoint_t driver_e, message *mess_ptr)
{
/* Perform I/O on a block device. The current thread is suspended until a reply
* comes in from the driver.
*/ */
int r, status = OK, proc_e = NONE, is_bdev, retry_count; int r, status, retry_count;
message mess_retry; message mess_retry;
is_bdev = IS_BDEV_RQ(mess_ptr->m_type); assert(IS_BDEV_RQ(mess_ptr->m_type));
mess_retry = *mess_ptr; mess_retry = *mess_ptr;
retry_count = 0; retry_count = 0;
if (!is_bdev) proc_e = mess_ptr->USER_ENDPT;
do { do {
r = drv_sendrec(driver_e, mess_ptr); r = drv_sendrec(driver_e, mess_ptr);
if (r == OK) { if (r == OK) {
if (is_bdev)
status = mess_ptr->BDEV_STATUS; status = mess_ptr->BDEV_STATUS;
else
status = mess_ptr->REP_STATUS;
if (status == ERESTART) { if (status == ERESTART) {
r = EDEADEPT; r = EDEADEPT;
*mess_ptr = mess_retry; *mess_ptr = mess_retry;
@ -652,39 +661,26 @@ message *mess_ptr; /* pointer to message for task */
printf("VFS: ELOCKED talking to %d\n", driver_e); printf("VFS: ELOCKED talking to %d\n", driver_e);
return(r); return(r);
} }
panic("call_task: can't send/receive: %d", r); panic("block_io: can't send/receive: %d", r);
} }
/* Did the process we did the sendrec() for get a result? */
if (!is_bdev && mess_ptr->REP_ENDPT != proc_e && mess_ptr->m_type != EIO) {
printf("VFS: strange device reply from %d, type = %d, "
"proc = %d (not %d) (2) ignored\n", mess_ptr->m_source,
mess_ptr->m_type, proc_e, mess_ptr->REP_ENDPT);
return(EIO);
} else if (!IS_DRV_REPLY(mess_ptr->m_type))
return(EIO);
return(OK); return(OK);
} }
/*===========================================================================* /*===========================================================================*
* asyn_io * * gen_io *
*===========================================================================*/ *===========================================================================*/
int asyn_io(endpoint_t drv_e, message *mess_ptr) int gen_io(endpoint_t drv_e, message *mess_ptr)
{ {
/* All file system I/O ultimately comes down to I/O on major/minor device /* Initiate I/O to a character driver. Do not wait for the reply. */
* pairs. These lead to calls on the following routines via the dmap table.
*/
int r; int r;
assert(!IS_BDEV_RQ(mess_ptr->m_type)); assert(!IS_BDEV_RQ(mess_ptr->m_type));
r = asynsend3(drv_e, mess_ptr, AMF_NOREPLY); r = asynsend3(drv_e, mess_ptr, AMF_NOREPLY);
if (r != OK) panic("VFS: asynsend in asyn_io failed: %d", r); if (r != OK) panic("VFS: asynsend in gen_io failed: %d", r);
/* Fake a SUSPEND */ /* Fake a SUSPEND */
mess_ptr->REP_STATUS = SUSPEND; mess_ptr->REP_STATUS = SUSPEND;
@ -709,7 +705,7 @@ int ctty_io(
if (fp->fp_tty == 0) { if (fp->fp_tty == 0) {
/* No controlling tty present anymore, return an I/O error. */ /* No controlling tty present anymore, return an I/O error. */
mess_ptr->REP_STATUS = EIO; return(EIO);
} else { } else {
/* Substitute the controlling terminal device. */ /* Substitute the controlling terminal device. */
dp = &dmap[major(fp->fp_tty)]; dp = &dmap[major(fp->fp_tty)];
@ -725,10 +721,8 @@ int ctty_io(
return(EIO); return(EIO);
} }
(*dp->dmap_io)(dp->dmap_driver, mess_ptr); return (*dp->dmap_io)(dp->dmap_driver, mess_ptr);
} }
return(OK);
} }
@ -800,8 +794,8 @@ int clone_opcl(
r = (*dp->dmap_io)(dp->dmap_driver, &dev_mess); r = (*dp->dmap_io)(dp->dmap_driver, &dev_mess);
if (r != OK) return(r); if (r != OK) return(r);
if (op == DEV_OPEN && dev_style_asyn(dp->dmap_style)) { if (op == DEV_OPEN) {
/* Wait for reply when driver is asynchronous */ /* Wait for the reply. */
fp->fp_task = dp->dmap_driver; fp->fp_task = dp->dmap_driver;
self->w_task = dp->dmap_driver; self->w_task = dp->dmap_driver;
self->w_drv_sendrec = &dev_mess; self->w_drv_sendrec = &dev_mess;
@ -968,6 +962,50 @@ void open_reply(void)
worker_signal(wp); /* Continue open */ worker_signal(wp); /* Continue open */
} }
/*===========================================================================*
* task_reply *
*===========================================================================*/
void task_reply(void)
{
/* A character driver has results for a read, write, or ioctl call. */
struct fproc *rfp;
struct worker_thread *wp;
endpoint_t proc_e;
int slot;
proc_e = job_m_in.REP_ENDPT;
if (proc_e == VFS_PROC_NR)
proc_e = find_suspended_ep(job_m_in.m_source, job_m_in.REP_IO_GRANT);
else
printf("VFS: endpoint %u from %u is not VFS\n",
proc_e, job_m_in.m_source);
if (proc_e == NONE) {
printf("VFS: proc with grant %d from %d not found\n",
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 {
/* If there is a thread active for this process, we assume that this
* thread aims to cancel the ongoing operation. In that case, wake up
* the thread to let it finish unpausing the process. Otherwise, revive
* the process as usual.
*/
if (isokendpt(proc_e, &slot) != OK) return;
rfp = &fproc[slot];
wp = worker_get(rfp->fp_wtid);
if (wp != NULL && wp->w_task == who_e) {
assert(!fp_is_blocked(rfp));
*wp->w_drv_sendrec = job_m_in;
worker_signal(wp); /* Continue cancel */
} else {
revive(proc_e, job_m_in.REP_STATUS);
}
}
}
/*===========================================================================* /*===========================================================================*
* dev_reply * * dev_reply *
*===========================================================================*/ *===========================================================================*/

View file

@ -180,11 +180,11 @@ int flags; /* device flags */
switch (style) { switch (style) {
case STYLE_DEV: case STYLE_DEV:
dp->dmap_opcl = gen_opcl; dp->dmap_opcl = gen_opcl;
dp->dmap_io = asyn_io; dp->dmap_io = gen_io;
break; break;
case STYLE_TTY: case STYLE_TTY:
dp->dmap_opcl = tty_opcl; dp->dmap_opcl = tty_opcl;
dp->dmap_io = asyn_io; dp->dmap_io = gen_io;
break; break;
case STYLE_CTTY: case STYLE_CTTY:
dp->dmap_opcl = ctty_opcl; dp->dmap_opcl = ctty_opcl;
@ -192,7 +192,7 @@ int flags; /* device flags */
break; break;
case STYLE_CLONE: case STYLE_CLONE:
dp->dmap_opcl = clone_opcl; dp->dmap_opcl = clone_opcl;
dp->dmap_io = asyn_io; dp->dmap_io = gen_io;
break; break;
default: default:
return(EINVAL); return(EINVAL);

View file

@ -40,7 +40,7 @@ EXTERN unsigned long calls_stats[NCALLS];
#endif #endif
/* Thread related prototypes */ /* Thread related prototypes */
static void *do_async_dev_result(void *arg); static void *do_char_dev_result(void *arg);
static void *do_control_msgs(void *arg); static void *do_control_msgs(void *arg);
static void *do_fs_reply(struct job *job); static void *do_fs_reply(struct job *job);
static void *do_work(void *arg); static void *do_work(void *arg);
@ -137,9 +137,8 @@ int main(void)
dp = get_dmap(who_e); dp = get_dmap(who_e);
if (dp != NULL) { if (dp != NULL) {
if (!IS_BDEV_RS(call_nr) && if (!IS_BDEV_RS(call_nr)) {
dev_style_asyn(dp->dmap_style)) { handle_work(do_char_dev_result);
handle_work(do_async_dev_result);
} else { } else {
if (dp->dmap_servicing == NONE) { if (dp->dmap_servicing == NONE) {
@ -211,31 +210,17 @@ static void handle_work(void *(*func)(void *arg))
} }
/*===========================================================================* /*===========================================================================*
* do_async_dev_result * * do_char_dev_result *
*===========================================================================*/ *===========================================================================*/
static void *do_async_dev_result(void *arg) static void *do_char_dev_result(void *arg)
{ {
endpoint_t endpt;
struct job my_job; struct job my_job;
my_job = *((struct job *) arg); my_job = *((struct job *) arg);
fp = my_job.j_fp; fp = my_job.j_fp;
/* An asynchronous character driver has results for us */ /* A character driver has results for us. */
if (job_call_nr == DEV_REVIVE) { if (job_call_nr == DEV_REVIVE) task_reply();
endpt = job_m_in.REP_ENDPT;
if (endpt == VFS_PROC_NR)
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",
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, job_m_in.REP_STATUS);
}
else if (job_call_nr == DEV_OPEN_REPL) open_reply(); 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_REOPEN_REPL) reopen_reply();
else if (job_call_nr == DEV_CLOSE_REPL) close_reply(); else if (job_call_nr == DEV_CLOSE_REPL) close_reply();

View file

@ -529,10 +529,9 @@ void unpause(endpoint_t proc_e)
*/ */
register struct fproc *rfp, *org_fp; register struct fproc *rfp, *org_fp;
int slot, blocked_on, fild, status = EINTR, major_dev, minor_dev; int slot, blocked_on, fild, status = EINTR;
struct filp *f; struct filp *f;
dev_t dev; dev_t dev;
message mess;
int wasreviving = 0; int wasreviving = 0;
if (isokendpt(proc_e, &slot) != OK) { if (isokendpt(proc_e, &slot) != OK) {
@ -584,31 +583,12 @@ void unpause(endpoint_t proc_e)
rfp->fp_endpoint, fild); rfp->fp_endpoint, fild);
} }
dev = (dev_t) f->filp_vno->v_sdev; /* device hung on */ dev = (dev_t) f->filp_vno->v_sdev; /* device hung on */
major_dev = major(dev);
minor_dev = minor(dev);
mess.DEVICE = minor_dev;
mess.USER_ENDPT = rfp->fp_ioproc;
mess.IO_GRANT = (char *) rfp->fp_grant;
/* Tell kernel R or W. Mode is from current call, not open. */
mess.COUNT = rfp->fp_block_callnr == READ ? R_BIT : W_BIT;
mess.m_type = CANCEL;
org_fp = fp; org_fp = fp;
fp = rfp; /* hack - ctty_io uses fp */ fp = rfp; /* hack - ctty_io uses fp */
(*dmap[major_dev].dmap_io)(rfp->fp_task, &mess); status = dev_cancel(dev);
fp = org_fp; fp = org_fp;
status = mess.REP_STATUS;
if (status == SUSPEND)
return; /* Process will be revived at a
* later time.
*/
if (status == EAGAIN) status = EINTR;
if (GRANT_VALID(rfp->fp_grant)) {
(void) cpf_revoke(rfp->fp_grant);
rfp->fp_grant = GRANT_INVALID;
}
break; break;
default : default :
panic("VFS: unknown block reason: %d", blocked_on); panic("VFS: unknown block reason: %d", blocked_on);

View file

@ -38,8 +38,7 @@ int bdev_close(dev_t dev);
int dev_io(int op, dev_t dev, endpoint_t proc_e, void *buf, off_t pos, int dev_io(int op, dev_t dev, endpoint_t proc_e, void *buf, off_t pos,
size_t bytes, int flags, int suspend_reopen); size_t bytes, int flags, int suspend_reopen);
int gen_opcl(int op, dev_t dev, endpoint_t task_nr, int flags); int gen_opcl(int op, dev_t dev, endpoint_t task_nr, int flags);
int gen_io(endpoint_t driver_e, message *mess_ptr); int gen_io(endpoint_t drv_e, message *mess_ptr);
int asyn_io(endpoint_t drv_e, message *mess_ptr);
int no_dev(int op, dev_t dev, endpoint_t proc, int flags); int no_dev(int op, dev_t dev, endpoint_t proc, int flags);
int no_dev_io(endpoint_t, message *); int no_dev_io(endpoint_t, message *);
int tty_opcl(int op, dev_t dev, endpoint_t proc, int flags); int tty_opcl(int op, dev_t dev, endpoint_t proc, int flags);
@ -47,12 +46,14 @@ int ctty_opcl(int op, dev_t dev, endpoint_t proc, int flags);
int clone_opcl(int op, dev_t dev, endpoint_t proc, int flags); int clone_opcl(int op, dev_t dev, endpoint_t proc, int flags);
int ctty_io(endpoint_t task_nr, message *mess_ptr); int ctty_io(endpoint_t task_nr, message *mess_ptr);
int do_ioctl(message *m_out); int do_ioctl(message *m_out);
int dev_select(dev_t dev, int ops);
int dev_cancel(dev_t dev);
void pm_setsid(endpoint_t proc_e); void pm_setsid(endpoint_t proc_e);
void bdev_up(int major); void bdev_up(int major);
void cdev_up(int major); void cdev_up(int major);
endpoint_t find_suspended_ep(endpoint_t driver, cp_grant_id_t g);
void reopen_reply(void); void reopen_reply(void);
void open_reply(void); void open_reply(void);
void task_reply(void);
/* dmap.c */ /* dmap.c */
void lock_dmap(struct dmap *dp); void lock_dmap(struct dmap *dp);

View file

@ -151,7 +151,7 @@ int read_write(struct fproc *rfp, int rw_flag, struct filp *f,
if (size > SSIZE_MAX) return(EINVAL); if (size > SSIZE_MAX) return(EINVAL);
op = (rw_flag == READING ? VFS_DEV_READ : VFS_DEV_WRITE); op = (rw_flag == READING ? DEV_READ_S : DEV_WRITE_S);
if (S_ISFIFO(vp->v_mode)) { /* Pipes */ if (S_ISFIFO(vp->v_mode)) { /* Pipes */
if (rfp->fp_cum_io_partial != 0) { if (rfp->fp_cum_io_partial != 0) {
@ -165,7 +165,7 @@ int read_write(struct fproc *rfp, int rw_flag, struct filp *f,
} else if (S_ISCHR(vp->v_mode)) { /* Character special files. */ } else if (S_ISCHR(vp->v_mode)) { /* Character special files. */
dev_t dev; dev_t dev;
int suspend_reopen; int suspend_reopen;
int op = (rw_flag == READING ? VFS_DEV_READ : VFS_DEV_WRITE); int op = (rw_flag == READING ? DEV_READ_S : DEV_WRITE_S);
if(rw_flag == PEEKING) { if(rw_flag == PEEKING) {
printf("read_write: peek on char device makes no sense\n"); printf("read_write: peek on char device makes no sense\n");

View file

@ -52,11 +52,9 @@ static int is_regular_file(struct filp *f);
static int is_pipe(struct filp *f); static int is_pipe(struct filp *f);
static int is_supported_major(struct filp *f); static int is_supported_major(struct filp *f);
static void select_lock_filp(struct filp *f, int ops); static void select_lock_filp(struct filp *f, int ops);
static int select_request_async(struct filp *f, int *ops, int block);
static int select_request_file(struct filp *f, int *ops, int block); static int select_request_file(struct filp *f, int *ops, int block);
static int select_request_major(struct filp *f, int *ops, int block); static int select_request_major(struct filp *f, int *ops, int block);
static int select_request_pipe(struct filp *f, int *ops, int block); static int select_request_pipe(struct filp *f, int *ops, int block);
static int select_request_sync(struct filp *f, int *ops, int block);
static void select_cancel_all(struct selectentry *e); static void select_cancel_all(struct selectentry *e);
static void select_cancel_filp(struct filp *f); static void select_cancel_filp(struct filp *f);
static void select_return(struct selectentry *); static void select_return(struct selectentry *);
@ -336,13 +334,16 @@ static int is_supported_major(struct filp *f)
} }
/*===========================================================================* /*===========================================================================*
* select_request_async * * select_request_major *
*===========================================================================*/ *===========================================================================*/
static int select_request_async(struct filp *f, int *ops, int block) static int select_request_major(struct filp *f, int *ops, int block)
{ {
int r, rops, major; int r, rops, major;
struct dmap *dp; struct dmap *dp;
major = major(f->filp_vno->v_sdev);
if (major < 0 || major >= NR_DEVICES) return(ENXIO);
rops = *ops; rops = *ops;
/* By default, nothing to do */ /* By default, nothing to do */
@ -375,20 +376,15 @@ static int select_request_async(struct filp *f, int *ops, int block)
if (f->filp_select_flags & FSF_BUSY) if (f->filp_select_flags & FSF_BUSY)
return(SUSPEND); return(SUSPEND);
major = major(f->filp_vno->v_sdev);
if (major < 0 || major >= NR_DEVICES) return(ENXIO);
dp = &dmap[major]; dp = &dmap[major];
if (dp->dmap_sel_filp) if (dp->dmap_sel_filp)
return(SUSPEND); return(SUSPEND);
f->filp_select_flags &= ~FSF_UPDATE; f->filp_select_flags &= ~FSF_UPDATE;
r = dev_io(VFS_DEV_SELECT, f->filp_vno->v_sdev, rops, NULL, 0, 0, 0, FALSE); r = dev_select(f->filp_vno->v_sdev, rops);
if (r < 0 && r != SUSPEND) if (r != OK)
return(r); return(r);
if (r != SUSPEND)
panic("select_request_asynch: expected SUSPEND got: %d", r);
dp->dmap_sel_filp = f; dp->dmap_sel_filp = f;
f->filp_select_flags |= FSF_BUSY; f->filp_select_flags |= FSF_BUSY;
@ -405,40 +401,6 @@ static int select_request_file(struct filp *UNUSED(f), int *UNUSED(ops),
return(OK); return(OK);
} }
/*===========================================================================*
* select_request_major *
*===========================================================================*/
static int select_request_major(struct filp *f, int *ops, int block)
{
int major, r;
major = major(f->filp_vno->v_sdev);
if (major < 0 || major >= NR_DEVICES) return(ENXIO);
if (dev_style_asyn(dmap[major].dmap_style))
r = select_request_async(f, ops, block);
else
r = select_request_sync(f, ops, block);
return(r);
}
/*===========================================================================*
* select_request_sync *
*===========================================================================*/
static int select_request_sync(struct filp *f, int *ops, int block)
{
int rops;
rops = *ops;
if (block) rops |= SEL_NOTIFY;
*ops = dev_io(VFS_DEV_SELECT, f->filp_vno->v_sdev, rops, NULL, 0, 0, 0,FALSE);
if (*ops < 0)
return(*ops);
return(OK);
}
/*===========================================================================* /*===========================================================================*
* select_request_pipe * * select_request_pipe *
*===========================================================================*/ *===========================================================================*/