VFS - no CANCEL for async non-blocking operations
- if an operation (R, W, IOCTL) is non blocking, a flag is set and sent to the device. - nothing changes for sync devices - asyn devices should reply asap if an operation is non-blocking. We must trust the devices, but we had to trust them anyway to reply to CANCEL correctly - we safe sending CANCEL commands to asyn devices. This greatly simplifies the protocol. Asynchronous devices can always reply when a reply is ready and do not need to deal with other situations - currently, none of our drivers use the flags since they drive virtual devices which do not block
This commit is contained in:
parent
f19d8df184
commit
72b7abd1a1
8 changed files with 32 additions and 16 deletions
|
@ -14,7 +14,8 @@ FORWARD _PROTOTYPE( struct device * hello_prepare, (dev_t device) );
|
|||
FORWARD _PROTOTYPE( int hello_transfer, (endpoint_t endpt, int opcode,
|
||||
u64_t position, iovec_t *iov,
|
||||
unsigned int nr_req,
|
||||
endpoint_t user_endpt) );
|
||||
endpoint_t user_endpt,
|
||||
unsigned int flags) );
|
||||
|
||||
/* SEF functions and variables. */
|
||||
FORWARD _PROTOTYPE( void sef_local_startup, (void) );
|
||||
|
@ -63,7 +64,8 @@ PRIVATE struct device * hello_prepare(dev_t UNUSED(dev))
|
|||
}
|
||||
|
||||
PRIVATE int hello_transfer(endpoint_t endpt, int opcode, u64_t position,
|
||||
iovec_t *iov, unsigned nr_req, endpoint_t UNUSED(user_endpt))
|
||||
iovec_t *iov, unsigned nr_req, endpoint_t UNUSED(user_endpt),
|
||||
unsigned int UNUSED(flags))
|
||||
{
|
||||
int bytes, ret;
|
||||
|
||||
|
|
|
@ -25,7 +25,7 @@ PRIVATE int log_device = -1; /* current device */
|
|||
FORWARD _PROTOTYPE( struct device *log_prepare, (dev_t device) );
|
||||
FORWARD _PROTOTYPE( int log_transfer, (endpoint_t endpt, int opcode,
|
||||
u64_t position, iovec_t *iov, unsigned int nr_req,
|
||||
endpoint_t user_endpt) );
|
||||
endpoint_t user_endpt, unsigned int flags) );
|
||||
FORWARD _PROTOTYPE( int log_do_open, (message *m_ptr) );
|
||||
FORWARD _PROTOTYPE( int log_cancel, (message *m_ptr) );
|
||||
FORWARD _PROTOTYPE( int log_select, (message *m_ptr) );
|
||||
|
@ -281,7 +281,8 @@ PRIVATE int log_transfer(
|
|||
u64_t UNUSED(position), /* offset on device to read or write */
|
||||
iovec_t *iov, /* pointer to read or write request vector */
|
||||
unsigned int nr_req, /* length of request vector */
|
||||
endpoint_t user_endpt /* endpoint of user process */
|
||||
endpoint_t user_endpt, /* endpoint of user process */
|
||||
unsigned int UNUSED(flags)
|
||||
)
|
||||
{
|
||||
/* Read or write one the driver's minor devices. */
|
||||
|
|
|
@ -47,7 +47,7 @@ PRIVATE int openct[NR_DEVS];
|
|||
FORWARD _PROTOTYPE( struct device *m_prepare, (dev_t device) );
|
||||
FORWARD _PROTOTYPE( int m_transfer, (endpoint_t endpt, int opcode,
|
||||
u64_t position, iovec_t *iov, unsigned int nr_req,
|
||||
endpoint_t user_endpt) );
|
||||
endpoint_t user_endpt, unsigned int flags) );
|
||||
FORWARD _PROTOTYPE( int m_do_open, (message *m_ptr) );
|
||||
FORWARD _PROTOTYPE( int m_do_close, (message *m_ptr) );
|
||||
|
||||
|
@ -231,7 +231,8 @@ PRIVATE int m_transfer(
|
|||
u64_t pos64, /* offset on device to read or write */
|
||||
iovec_t *iov, /* pointer to read or write request vector */
|
||||
unsigned int nr_req, /* length of request vector */
|
||||
endpoint_t UNUSED(user_endpt) /* endpoint of user process */
|
||||
endpoint_t UNUSED(user_endpt),/* endpoint of user process */
|
||||
unsigned int UNUSED(flags)
|
||||
)
|
||||
{
|
||||
/* Read or write one the driver's character devices. */
|
||||
|
|
|
@ -23,7 +23,7 @@ extern int errno; /* error number for PM calls */
|
|||
FORWARD _PROTOTYPE( struct device *r_prepare, (dev_t device) );
|
||||
FORWARD _PROTOTYPE( int r_transfer, (endpoint_t endpt, int opcode,
|
||||
u64_t position, iovec_t *iov, unsigned int nr_req,
|
||||
endpoint_t user_endpt) );
|
||||
endpoint_t user_endpt, unsigned int flags) );
|
||||
FORWARD _PROTOTYPE( int r_do_open, (message *m_ptr) );
|
||||
FORWARD _PROTOTYPE( void r_random, (message *m_ptr) );
|
||||
FORWARD _PROTOTYPE( void r_updatebin, (int source,
|
||||
|
@ -142,7 +142,8 @@ PRIVATE int r_transfer(
|
|||
u64_t position, /* offset on device to read or write */
|
||||
iovec_t *iov, /* pointer to read or write request vector */
|
||||
unsigned int nr_req, /* length of request vector */
|
||||
endpoint_t UNUSED(user_endpt) /* endpoint of user process */
|
||||
endpoint_t UNUSED(user_endpt),/* endpoint of user process */
|
||||
unsigned int UNUSED(flags)
|
||||
)
|
||||
{
|
||||
/* Read or write one the driver's minor devices. */
|
||||
|
|
|
@ -11,7 +11,7 @@ struct chardriver {
|
|||
_PROTOTYPE( struct device *(*cdr_prepare), (dev_t device) );
|
||||
_PROTOTYPE( int (*cdr_transfer), (endpoint_t endpt, int opcode,
|
||||
u64_t position, iovec_t *iov, unsigned int nr_req,
|
||||
endpoint_t user_endpt) );
|
||||
endpoint_t user_endpt, unsigned int flags) );
|
||||
_PROTOTYPE( void (*cdr_cleanup), (void) );
|
||||
_PROTOTYPE( void (*cdr_alarm), (message *m_ptr) );
|
||||
_PROTOTYPE( int (*cdr_cancel), (message *m_ptr) );
|
||||
|
|
|
@ -225,6 +225,9 @@
|
|||
#define HIGHPOS m2_l2 /* file offset (high 4 bytes) */
|
||||
#define ADDRESS m2_p1 /* core buffer address */
|
||||
#define IO_GRANT m2_p1 /* grant id (for DEV_*_S variants) */
|
||||
#define FLAGS m2_s1 /* operation flags */
|
||||
|
||||
#define FLG_OP_NONBLOCK 0x1 /* operation is non blocking */
|
||||
|
||||
/* Field names for DEV_SELECT messages to character device drivers. */
|
||||
#define DEV_MINOR m2_i1 /* minor device */
|
||||
|
|
|
@ -241,8 +241,10 @@ PRIVATE int do_rdwt(struct chardriver *cdp, message *mp)
|
|||
if ((*cdp->cdr_prepare)(mp->DEVICE) == NULL) return(ENXIO);
|
||||
|
||||
/* Create a one element scatter/gather vector for the buffer. */
|
||||
if(mp->m_type == DEV_READ_S) opcode = DEV_GATHER_S;
|
||||
else opcode = DEV_SCATTER_S;
|
||||
if(mp->m_type == DEV_READ_S)
|
||||
opcode = DEV_GATHER_S;
|
||||
else
|
||||
opcode = DEV_SCATTER_S;
|
||||
|
||||
iovec1.iov_addr = (vir_bytes) mp->IO_GRANT;
|
||||
iovec1.iov_size = mp->COUNT;
|
||||
|
@ -250,7 +252,7 @@ PRIVATE int do_rdwt(struct chardriver *cdp, message *mp)
|
|||
/* Transfer bytes from/to the device. */
|
||||
position= make64(mp->POSITION, mp->HIGHPOS);
|
||||
r = (*cdp->cdr_transfer)(mp->m_source, opcode, position, &iovec1, 1,
|
||||
mp->USER_ENDPT);
|
||||
mp->USER_ENDPT, mp->FLAGS);
|
||||
|
||||
/* Return the number of bytes transferred or an error code. */
|
||||
return(r == OK ? (int) (mp->COUNT - iovec1.iov_size) : r);
|
||||
|
@ -290,7 +292,7 @@ PRIVATE int do_vrdwt(struct chardriver *cdp, message *mp)
|
|||
opcode = mp->m_type;
|
||||
position= make64(mp->POSITION, mp->HIGHPOS);
|
||||
r = (*cdp->cdr_transfer)(mp->m_source, opcode, position, iovec, nr_req,
|
||||
mp->USER_ENDPT);
|
||||
mp->USER_ENDPT, mp->FLAGS);
|
||||
|
||||
/* Copy the I/O vector back to the caller. */
|
||||
if (OK != sys_safecopyto(mp->m_source, (vir_bytes) mp->IO_GRANT,
|
||||
|
|
|
@ -409,7 +409,7 @@ PUBLIC int dev_io(
|
|||
int safe, minor_dev, major_dev;
|
||||
void *buf_used;
|
||||
endpoint_t ioproc;
|
||||
int ret;
|
||||
int ret, is_asyn;
|
||||
|
||||
pos_lo = ex64lo(pos);
|
||||
pos_high = ex64hi(pos);
|
||||
|
@ -447,6 +447,8 @@ PUBLIC int dev_io(
|
|||
(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.
|
||||
*/
|
||||
|
@ -458,6 +460,10 @@ PUBLIC int dev_io(
|
|||
dev_mess.POSITION = pos_lo;
|
||||
dev_mess.COUNT = bytes;
|
||||
dev_mess.HIGHPOS = pos_high;
|
||||
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;
|
||||
|
@ -476,7 +482,7 @@ PUBLIC int dev_io(
|
|||
|
||||
/* Task has completed. See if call completed. */
|
||||
if (ret == SUSPEND) {
|
||||
if ((flags & O_NONBLOCK) && !dev_style_asyn(dp->dmap_style)) {
|
||||
if ((flags & O_NONBLOCK) && !is_asyn) {
|
||||
/* Not supposed to block. */
|
||||
ret = cancel_nblock(dp, minor_dev, call_nr, ioproc, gid);
|
||||
if (ret == EINTR)
|
||||
|
@ -491,7 +497,7 @@ PUBLIC int dev_io(
|
|||
fp->fp_grant = gid; /* revoke this when unsuspended. */
|
||||
fp->fp_ioproc = ioproc;
|
||||
|
||||
if (flags & O_NONBLOCK) {
|
||||
if ((flags & O_NONBLOCK) && !is_asyn) {
|
||||
/* Not supposed to block, send cancel message */
|
||||
cancel_nblock(dp, minor_dev, call_nr, ioproc, gid);
|
||||
/*
|
||||
|
|
Loading…
Reference in a new issue