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 */
|
#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
|
||||||
|
|
|
@ -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,9 +216,11 @@ 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);
|
||||||
|
@ -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)
|
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,39 +261,27 @@ 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;
|
default:
|
||||||
case VFS_DEV_SELECT:
|
panic("VFS: unknown operation %d", op);
|
||||||
*op = DEV_SELECT;
|
|
||||||
break;
|
|
||||||
default:
|
|
||||||
panic("VFS: unknown operation %d for safe I/O conversion", *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)) {
|
|
||||||
*io_ept = VFS_PROC_NR;
|
|
||||||
return(1);
|
|
||||||
}
|
|
||||||
|
|
||||||
/* Not converted to a safe operation (because there is no copying involved in
|
return gid;
|
||||||
* 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 */
|
||||||
off_t pos, /* byte position */
|
off_t pos, /* byte position */
|
||||||
size_t bytes, /* how many bytes to transfer */
|
size_t bytes, /* how many bytes to transfer */
|
||||||
|
@ -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.COUNT = bytes;
|
dev_mess.REQUEST = bytes;
|
||||||
dev_mess.HIGHPOS = pos_high;
|
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;
|
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. */
|
||||||
|
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. */
|
return SUSPEND;
|
||||||
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;
|
|
||||||
}
|
}
|
||||||
|
|
||||||
/*===========================================================================*
|
/*===========================================================================*
|
||||||
|
@ -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 *
|
||||||
*===========================================================================*/
|
*===========================================================================*/
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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();
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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);
|
||||||
|
|
|
@ -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");
|
||||||
|
|
|
@ -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 *
|
||||||
*===========================================================================*/
|
*===========================================================================*/
|
||||||
|
|
Loading…
Reference in a new issue