From 72b7abd1a175bffcadde6592e96a3f64043c2d59 Mon Sep 17 00:00:00 2001 From: Tomas Hruby Date: Mon, 20 Feb 2012 13:19:29 +0000 Subject: [PATCH] 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 --- drivers/hello/hello.c | 6 ++++-- drivers/log/log.c | 5 +++-- drivers/memory/memory.c | 5 +++-- drivers/random/main.c | 5 +++-- include/minix/chardriver.h | 2 +- include/minix/com.h | 3 +++ lib/libchardriver/chardriver.c | 10 ++++++---- servers/vfs/device.c | 12 +++++++++--- 8 files changed, 32 insertions(+), 16 deletions(-) diff --git a/drivers/hello/hello.c b/drivers/hello/hello.c index 21f60b537..c317563a4 100644 --- a/drivers/hello/hello.c +++ b/drivers/hello/hello.c @@ -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; diff --git a/drivers/log/log.c b/drivers/log/log.c index 7d08dc405..98aa7cdb1 100644 --- a/drivers/log/log.c +++ b/drivers/log/log.c @@ -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. */ diff --git a/drivers/memory/memory.c b/drivers/memory/memory.c index e1805a01b..df297aebc 100644 --- a/drivers/memory/memory.c +++ b/drivers/memory/memory.c @@ -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. */ diff --git a/drivers/random/main.c b/drivers/random/main.c index 492d19ff9..e6cf2ea3f 100644 --- a/drivers/random/main.c +++ b/drivers/random/main.c @@ -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. */ diff --git a/include/minix/chardriver.h b/include/minix/chardriver.h index fe3f64d79..79089a565 100644 --- a/include/minix/chardriver.h +++ b/include/minix/chardriver.h @@ -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) ); diff --git a/include/minix/com.h b/include/minix/com.h index c1c4f6f40..c7f03fb67 100644 --- a/include/minix/com.h +++ b/include/minix/com.h @@ -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 */ diff --git a/lib/libchardriver/chardriver.c b/lib/libchardriver/chardriver.c index 2d0517a78..c8cf63f15 100644 --- a/lib/libchardriver/chardriver.c +++ b/lib/libchardriver/chardriver.c @@ -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, diff --git a/servers/vfs/device.c b/servers/vfs/device.c index 8626550de..4cb5fdb67 100644 --- a/servers/vfs/device.c +++ b/servers/vfs/device.c @@ -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); /* -- 2.44.0