VFS: remove support for sync char driver protocol
Change-Id: I57cc870a053b813b3a3fc45da46606ea84fe4cb1
This commit is contained in:
parent
c7fbafe1ad
commit
87aefd7eb2
8 changed files with 237 additions and 279 deletions
|
@ -43,12 +43,4 @@
|
|||
*/
|
||||
#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
|
||||
|
|
|
@ -8,8 +8,8 @@
|
|||
* bdev_open: open a block device
|
||||
* bdev_close: close a block 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_io: generic call to a task to perform an I/O operation
|
||||
* gen_opcl: generic call to a character driver to perform an open/close
|
||||
* 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_io: i/o processing for devices that don't exist
|
||||
* tty_opcl: perform tty-specific processing for open/close
|
||||
|
@ -17,6 +17,9 @@
|
|||
* ctty_io: perform controlling-tty-specific processing for I/O
|
||||
* pm_setsid: perform VFS's side of setsid 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"
|
||||
|
@ -38,9 +41,10 @@
|
|||
#include "vmnt.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 int safe_io_conversion(endpoint_t, cp_grant_id_t *, int *,
|
||||
endpoint_t *, void **, size_t, u32_t *);
|
||||
|
||||
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. */
|
||||
struct dmap *dp;
|
||||
u32_t dummy;
|
||||
cp_grant_id_t gid;
|
||||
message dev_mess;
|
||||
int op, major_dev, minor_dev;
|
||||
int major_dev, minor_dev;
|
||||
|
||||
major_dev = major(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. */
|
||||
op = VFS_DEV_IOCTL;
|
||||
(void) safe_io_conversion(dp->dmap_driver, &gid, &op, &proc_e, &buf, req,
|
||||
&dummy);
|
||||
gid = make_grant(dp->dmap_driver, proc_e, BDEV_IOCTL, buf, req);
|
||||
|
||||
/* Set up the message passed to the task. */
|
||||
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;
|
||||
|
||||
/* Call the task. */
|
||||
gen_io(dp->dmap_driver, &dev_mess);
|
||||
block_io(dp->dmap_driver, &dev_mess);
|
||||
|
||||
/* Clean up. */
|
||||
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 *
|
||||
*===========================================================================*/
|
||||
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
|
||||
* which process it was.
|
||||
|
@ -215,9 +216,11 @@ endpoint_t find_suspended_ep(endpoint_t driver, cp_grant_id_t g)
|
|||
if(rfp->fp_pid == PID_FREE)
|
||||
continue;
|
||||
|
||||
if(rfp->fp_blocked_on == FP_BLOCKED_ON_OTHER &&
|
||||
rfp->fp_task == driver && rfp->fp_grant == g)
|
||||
if (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(NONE);
|
||||
|
@ -225,40 +228,29 @@ endpoint_t find_suspended_ep(endpoint_t driver, cp_grant_id_t g)
|
|||
|
||||
|
||||
/*===========================================================================*
|
||||
* safe_io_conversion *
|
||||
* make_grant *
|
||||
*===========================================================================*/
|
||||
static int safe_io_conversion(driver, gid, op, io_ept, buf, bytes, pos_lo)
|
||||
endpoint_t driver;
|
||||
cp_grant_id_t *gid;
|
||||
int *op;
|
||||
endpoint_t *io_ept;
|
||||
void **buf;
|
||||
size_t bytes;
|
||||
u32_t *pos_lo;
|
||||
static cp_grant_id_t make_grant(endpoint_t driver_e, endpoint_t user_e, int op,
|
||||
void *buf, size_t bytes)
|
||||
{
|
||||
/* Convert operation to the 'safe' variant (i.e., grant based) if applicable.
|
||||
* If no copying of data is involved, there is also no need to convert. */
|
||||
|
||||
int access = 0;
|
||||
/* Create a magic grant for the given operation and buffer. */
|
||||
cp_grant_id_t gid;
|
||||
int access;
|
||||
size_t size;
|
||||
|
||||
*gid = GRANT_INVALID; /* Grant to buffer */
|
||||
|
||||
switch(*op) {
|
||||
case VFS_DEV_READ:
|
||||
case VFS_DEV_WRITE:
|
||||
/* 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");
|
||||
switch (op) {
|
||||
case DEV_READ_S:
|
||||
case DEV_WRITE_S:
|
||||
gid = cpf_grant_magic(driver_e, user_e, (vir_bytes) buf, bytes,
|
||||
op == DEV_READ_S ? CPF_WRITE : CPF_READ);
|
||||
break;
|
||||
case VFS_DEV_IOCTL:
|
||||
*pos_lo = *io_ept; /* Old endpoint in POSITION field. */
|
||||
*op = DEV_IOCTL_S;
|
||||
|
||||
case DEV_IOCTL_S:
|
||||
case BDEV_IOCTL:
|
||||
/* 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_IOW(bytes)) access |= CPF_READ;
|
||||
if(_MINIX_IOCTL_BIG(bytes))
|
||||
|
@ -269,39 +261,27 @@ u32_t *pos_lo;
|
|||
/* Grant access to the buffer even if no I/O happens with the ioctl, in
|
||||
* order to disambiguate requests with DEV_IOCTL_S.
|
||||
*/
|
||||
*gid = cpf_grant_magic(driver, *io_ept, (vir_bytes) *buf, size, access);
|
||||
if (*gid < 0)
|
||||
panic("VFS: cpf_grant_magic IOCTL buffer failed");
|
||||
gid = cpf_grant_magic(driver_e, user_e, (vir_bytes) buf, size, access);
|
||||
break;
|
||||
|
||||
break;
|
||||
case VFS_DEV_SELECT:
|
||||
*op = DEV_SELECT;
|
||||
break;
|
||||
default:
|
||||
panic("VFS: unknown operation %d for safe I/O conversion", *op);
|
||||
default:
|
||||
panic("VFS: unknown operation %d", op);
|
||||
}
|
||||
|
||||
/* If we have converted to a safe operation, I/O endpoint becomes VFS if it
|
||||
* wasn't already.
|
||||
*/
|
||||
if(GRANT_VALID(*gid)) {
|
||||
*io_ept = VFS_PROC_NR;
|
||||
return(1);
|
||||
}
|
||||
if (!GRANT_VALID(gid))
|
||||
panic("VFS: cpf_grant_magic failed");
|
||||
|
||||
/* Not converted to a safe operation (because there is no copying involved in
|
||||
* this operation).
|
||||
*/
|
||||
return(0);
|
||||
return gid;
|
||||
}
|
||||
|
||||
|
||||
/*===========================================================================*
|
||||
* 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 */
|
||||
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 */
|
||||
off_t pos, /* byte position */
|
||||
size_t bytes, /* how many bytes to transfer */
|
||||
|
@ -309,22 +289,17 @@ int dev_io(
|
|||
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;
|
||||
u32_t pos_lo, pos_high;
|
||||
message dev_mess;
|
||||
cp_grant_id_t gid = GRANT_INVALID;
|
||||
int safe, minor_dev, major_dev;
|
||||
void *buf_used;
|
||||
endpoint_t ioproc;
|
||||
int ret, is_asyn;
|
||||
cp_grant_id_t gid;
|
||||
int r, minor_dev, major_dev;
|
||||
|
||||
pos_lo = ex64lo(pos);
|
||||
pos_high = ex64hi(pos);
|
||||
major_dev = major(dev);
|
||||
minor_dev = minor(dev);
|
||||
assert(op == DEV_READ_S || op == DEV_WRITE_S || op == DEV_IOCTL_S);
|
||||
|
||||
/* Determine task dmap. */
|
||||
major_dev = major(dev);
|
||||
minor_dev = minor(dev);
|
||||
dp = &dmap[major_dev];
|
||||
|
||||
/* See if driver is roughly valid. */
|
||||
|
@ -345,77 +320,42 @@ int dev_io(
|
|||
return(ENXIO);
|
||||
}
|
||||
|
||||
/* By default, these are right. */
|
||||
dev_mess.USER_ENDPT = proc_e;
|
||||
dev_mess.ADDRESS = buf;
|
||||
/* Create a grant for the buffer provided by the user process. */
|
||||
gid = make_grant(dp->dmap_driver, proc_e, op, buf, bytes);
|
||||
|
||||
/* Convert DEV_* to DEV_*_S variants. */
|
||||
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. */
|
||||
/* Set up the rest of the message that will be sent to the driver. */
|
||||
dev_mess.m_type = op;
|
||||
dev_mess.DEVICE = minor_dev;
|
||||
dev_mess.POSITION = pos_lo;
|
||||
dev_mess.COUNT = bytes;
|
||||
dev_mess.HIGHPOS = pos_high;
|
||||
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.HIGHPOS = ex64hi(pos);
|
||||
dev_mess.USER_ENDPT = VFS_PROC_NR;
|
||||
dev_mess.IO_GRANT = (void *) gid;
|
||||
dev_mess.FLAGS = 0;
|
||||
|
||||
if (flags & O_NONBLOCK)
|
||||
dev_mess.FLAGS |= FLG_OP_NONBLOCK;
|
||||
|
||||
/* This will be used if the i/o is suspended. */
|
||||
ioproc = dev_mess.USER_ENDPT;
|
||||
/* Send the request to the driver. */
|
||||
r = (*dp->dmap_io)(dp->dmap_driver, &dev_mess);
|
||||
|
||||
/* Call the task. */
|
||||
(*dp->dmap_io)(dp->dmap_driver, &dev_mess);
|
||||
if (r != OK) {
|
||||
cpf_revoke(gid);
|
||||
|
||||
if(dp->dmap_driver == NONE) {
|
||||
/* Driver has vanished. */
|
||||
printf("VFS: driver gone?!\n");
|
||||
if(safe) cpf_revoke(gid);
|
||||
return(EIO);
|
||||
return r;
|
||||
}
|
||||
|
||||
ret = dev_mess.REP_STATUS;
|
||||
/* Suspend the calling process until a reply arrives. */
|
||||
wait_for(dp->dmap_driver);
|
||||
assert(!GRANT_VALID(fp->fp_grant));
|
||||
fp->fp_grant = gid; /* revoke this when unsuspended. */
|
||||
fp->fp_ioproc = VFS_PROC_NR;
|
||||
|
||||
/* 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);
|
||||
}
|
||||
assert(!GRANT_VALID(fp->fp_grant));
|
||||
fp->fp_grant = gid; /* revoke this when unsuspended. */
|
||||
fp->fp_ioproc = ioproc;
|
||||
|
||||
return(SUSPEND);
|
||||
}
|
||||
|
||||
/* No suspend, or cancelled suspend, so I/O is over and can be cleaned up. */
|
||||
if(safe) cpf_revoke(gid);
|
||||
|
||||
return ret;
|
||||
return SUSPEND;
|
||||
}
|
||||
|
||||
/*===========================================================================*
|
||||
|
@ -450,7 +390,7 @@ int gen_opcl(
|
|||
dev_mess.BDEV_ID = 0;
|
||||
|
||||
/* Call the task. */
|
||||
r = gen_io(dp->dmap_driver, &dev_mess);
|
||||
r = block_io(dp->dmap_driver, &dev_mess);
|
||||
} else {
|
||||
dev_mess.m_type = op;
|
||||
dev_mess.DEVICE = minor_dev;
|
||||
|
@ -463,7 +403,7 @@ int gen_opcl(
|
|||
|
||||
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;
|
||||
self->w_task = dp->dmap_driver;
|
||||
self->w_drv_sendrec = &dev_mess;
|
||||
|
@ -593,7 +533,7 @@ int do_ioctl(message *UNUSED(m_out))
|
|||
if (S_ISBLK(vp->v_mode))
|
||||
r = bdev_ioctl(dev, who_e, ioctlrequest, argx);
|
||||
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);
|
||||
}
|
||||
|
||||
|
@ -604,31 +544,100 @@ int do_ioctl(message *UNUSED(m_out))
|
|||
|
||||
|
||||
/*===========================================================================*
|
||||
* gen_io *
|
||||
* dev_select *
|
||||
*===========================================================================*/
|
||||
int gen_io(driver_e, mess_ptr)
|
||||
endpoint_t driver_e; /* which endpoint to call */
|
||||
message *mess_ptr; /* pointer to message for task */
|
||||
int dev_select(dev_t dev, int ops)
|
||||
{
|
||||
/* All file system I/O ultimately comes down to I/O on major/minor device
|
||||
* pairs. These lead to calls on the following routines via the dmap table.
|
||||
/* Initiate a select call on a device. Return OK iff the request was sent. */
|
||||
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;
|
||||
|
||||
is_bdev = IS_BDEV_RQ(mess_ptr->m_type);
|
||||
assert(IS_BDEV_RQ(mess_ptr->m_type));
|
||||
mess_retry = *mess_ptr;
|
||||
retry_count = 0;
|
||||
|
||||
if (!is_bdev) proc_e = mess_ptr->USER_ENDPT;
|
||||
|
||||
do {
|
||||
r = drv_sendrec(driver_e, mess_ptr);
|
||||
if (r == OK) {
|
||||
if (is_bdev)
|
||||
status = mess_ptr->BDEV_STATUS;
|
||||
else
|
||||
status = mess_ptr->REP_STATUS;
|
||||
status = mess_ptr->BDEV_STATUS;
|
||||
if (status == ERESTART) {
|
||||
r = EDEADEPT;
|
||||
*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);
|
||||
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);
|
||||
}
|
||||
|
||||
|
||||
/*===========================================================================*
|
||||
* 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
|
||||
* pairs. These lead to calls on the following routines via the dmap table.
|
||||
*/
|
||||
|
||||
/* Initiate I/O to a character driver. Do not wait for the reply. */
|
||||
int r;
|
||||
|
||||
assert(!IS_BDEV_RQ(mess_ptr->m_type));
|
||||
|
||||
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 */
|
||||
mess_ptr->REP_STATUS = SUSPEND;
|
||||
|
@ -709,7 +705,7 @@ int ctty_io(
|
|||
|
||||
if (fp->fp_tty == 0) {
|
||||
/* No controlling tty present anymore, return an I/O error. */
|
||||
mess_ptr->REP_STATUS = EIO;
|
||||
return(EIO);
|
||||
} else {
|
||||
/* Substitute the controlling terminal device. */
|
||||
dp = &dmap[major(fp->fp_tty)];
|
||||
|
@ -725,10 +721,8 @@ int ctty_io(
|
|||
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);
|
||||
if (r != OK) return(r);
|
||||
|
||||
if (op == DEV_OPEN && dev_style_asyn(dp->dmap_style)) {
|
||||
/* Wait for reply when driver is asynchronous */
|
||||
if (op == DEV_OPEN) {
|
||||
/* Wait for the reply. */
|
||||
fp->fp_task = dp->dmap_driver;
|
||||
self->w_task = dp->dmap_driver;
|
||||
self->w_drv_sendrec = &dev_mess;
|
||||
|
@ -968,6 +962,50 @@ void open_reply(void)
|
|||
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 *
|
||||
*===========================================================================*/
|
||||
|
|
|
@ -180,11 +180,11 @@ int flags; /* device flags */
|
|||
switch (style) {
|
||||
case STYLE_DEV:
|
||||
dp->dmap_opcl = gen_opcl;
|
||||
dp->dmap_io = asyn_io;
|
||||
dp->dmap_io = gen_io;
|
||||
break;
|
||||
case STYLE_TTY:
|
||||
dp->dmap_opcl = tty_opcl;
|
||||
dp->dmap_io = asyn_io;
|
||||
dp->dmap_io = gen_io;
|
||||
break;
|
||||
case STYLE_CTTY:
|
||||
dp->dmap_opcl = ctty_opcl;
|
||||
|
@ -192,7 +192,7 @@ int flags; /* device flags */
|
|||
break;
|
||||
case STYLE_CLONE:
|
||||
dp->dmap_opcl = clone_opcl;
|
||||
dp->dmap_io = asyn_io;
|
||||
dp->dmap_io = gen_io;
|
||||
break;
|
||||
default:
|
||||
return(EINVAL);
|
||||
|
|
|
@ -40,7 +40,7 @@ EXTERN unsigned long calls_stats[NCALLS];
|
|||
#endif
|
||||
|
||||
/* 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_fs_reply(struct job *job);
|
||||
static void *do_work(void *arg);
|
||||
|
@ -137,9 +137,8 @@ int main(void)
|
|||
|
||||
dp = get_dmap(who_e);
|
||||
if (dp != NULL) {
|
||||
if (!IS_BDEV_RS(call_nr) &&
|
||||
dev_style_asyn(dp->dmap_style)) {
|
||||
handle_work(do_async_dev_result);
|
||||
if (!IS_BDEV_RS(call_nr)) {
|
||||
handle_work(do_char_dev_result);
|
||||
|
||||
} else {
|
||||
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;
|
||||
|
||||
my_job = *((struct job *) arg);
|
||||
fp = my_job.j_fp;
|
||||
|
||||
/* An asynchronous character driver has results for us */
|
||||
if (job_call_nr == DEV_REVIVE) {
|
||||
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);
|
||||
}
|
||||
/* A character driver has results for us. */
|
||||
if (job_call_nr == DEV_REVIVE) task_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_CLOSE_REPL) close_reply();
|
||||
|
|
|
@ -529,10 +529,9 @@ void unpause(endpoint_t proc_e)
|
|||
*/
|
||||
|
||||
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;
|
||||
dev_t dev;
|
||||
message mess;
|
||||
int wasreviving = 0;
|
||||
|
||||
if (isokendpt(proc_e, &slot) != OK) {
|
||||
|
@ -584,31 +583,12 @@ void unpause(endpoint_t proc_e)
|
|||
rfp->fp_endpoint, fild);
|
||||
}
|
||||
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;
|
||||
fp = rfp; /* hack - ctty_io uses fp */
|
||||
(*dmap[major_dev].dmap_io)(rfp->fp_task, &mess);
|
||||
status = dev_cancel(dev);
|
||||
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;
|
||||
default :
|
||||
panic("VFS: unknown block reason: %d", blocked_on);
|
||||
|
|
|
@ -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,
|
||||
size_t bytes, int flags, int suspend_reopen);
|
||||
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 asyn_io(endpoint_t drv_e, message *mess_ptr);
|
||||
int gen_io(endpoint_t drv_e, message *mess_ptr);
|
||||
int no_dev(int op, dev_t dev, endpoint_t proc, int flags);
|
||||
int no_dev_io(endpoint_t, message *);
|
||||
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 ctty_io(endpoint_t task_nr, message *mess_ptr);
|
||||
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 bdev_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 open_reply(void);
|
||||
void task_reply(void);
|
||||
|
||||
/* dmap.c */
|
||||
void lock_dmap(struct dmap *dp);
|
||||
|
|
|
@ -151,7 +151,7 @@ int read_write(struct fproc *rfp, int rw_flag, struct filp *f,
|
|||
|
||||
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 (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. */
|
||||
dev_t dev;
|
||||
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) {
|
||||
printf("read_write: peek on char device makes no sense\n");
|
||||
|
|
|
@ -52,11 +52,9 @@ static int is_regular_file(struct filp *f);
|
|||
static int is_pipe(struct filp *f);
|
||||
static int is_supported_major(struct filp *f);
|
||||
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_major(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_filp(struct filp *f);
|
||||
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;
|
||||
struct dmap *dp;
|
||||
|
||||
major = major(f->filp_vno->v_sdev);
|
||||
if (major < 0 || major >= NR_DEVICES) return(ENXIO);
|
||||
|
||||
rops = *ops;
|
||||
|
||||
/* 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)
|
||||
return(SUSPEND);
|
||||
|
||||
major = major(f->filp_vno->v_sdev);
|
||||
if (major < 0 || major >= NR_DEVICES) return(ENXIO);
|
||||
dp = &dmap[major];
|
||||
if (dp->dmap_sel_filp)
|
||||
return(SUSPEND);
|
||||
|
||||
f->filp_select_flags &= ~FSF_UPDATE;
|
||||
r = dev_io(VFS_DEV_SELECT, f->filp_vno->v_sdev, rops, NULL, 0, 0, 0, FALSE);
|
||||
if (r < 0 && r != SUSPEND)
|
||||
r = dev_select(f->filp_vno->v_sdev, rops);
|
||||
if (r != OK)
|
||||
return(r);
|
||||
|
||||
if (r != SUSPEND)
|
||||
panic("select_request_asynch: expected SUSPEND got: %d", r);
|
||||
|
||||
dp->dmap_sel_filp = f;
|
||||
f->filp_select_flags |= FSF_BUSY;
|
||||
|
||||
|
@ -405,40 +401,6 @@ static int select_request_file(struct filp *UNUSED(f), int *UNUSED(ops),
|
|||
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 *
|
||||
*===========================================================================*/
|
||||
|
|
Loading…
Reference in a new issue