From: David van Moolenbroek Date: Fri, 30 Aug 2013 11:33:56 +0000 (+0200) Subject: VFS: remove support for sync char driver protocol X-Git-Tag: v3.3.0~610 X-Git-Url: http://zhaoyanbai.com/repos/?a=commitdiff_plain;h=87aefd7eb2b98d5721d09f056da34f7b5da94e9a;p=minix.git VFS: remove support for sync char driver protocol Change-Id: I57cc870a053b813b3a3fc45da46606ea84fe4cb1 --- diff --git a/servers/vfs/const.h b/servers/vfs/const.h index b587f0e5f..d8c2f5c41 100644 --- a/servers/vfs/const.h +++ b/servers/vfs/const.h @@ -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 diff --git a/servers/vfs/device.c b/servers/vfs/device.c index 759cc6896..dffa310f9 100644 --- a/servers/vfs/device.c +++ b/servers/vfs/device.c @@ -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"); - - break; - case VFS_DEV_SELECT: - *op = DEV_SELECT; + gid = cpf_grant_magic(driver_e, user_e, (vir_bytes) buf, size, access); 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 - * wasn't already. - */ - if(GRANT_VALID(*gid)) { - *io_ept = VFS_PROC_NR; - return(1); + default: + panic("VFS: unknown operation %d", op); } - /* Not converted to a safe operation (because there is no copying involved in - * this operation). - */ - return(0); + if (!GRANT_VALID(gid)) + panic("VFS: cpf_grant_magic failed"); + + 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; - - pos_lo = ex64lo(pos); - pos_high = ex64hi(pos); - major_dev = major(dev); - minor_dev = minor(dev); + cp_grant_id_t gid; + int r, minor_dev, major_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; - - /* 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); + /* Create a grant for the buffer provided by the user process. */ + gid = make_grant(dp->dmap_driver, proc_e, op, buf, bytes); - 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; - - /* Call the task. */ - (*dp->dmap_io)(dp->dmap_driver, &dev_mess); - - if(dp->dmap_driver == NONE) { - /* Driver has vanished. */ - printf("VFS: driver gone?!\n"); - if(safe) cpf_revoke(gid); - return(EIO); - } - - ret = dev_mess.REP_STATUS; - - /* 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.. */ - } + /* Send the request to the driver. */ + r = (*dp->dmap_io)(dp->dmap_driver, &dev_mess); - /* 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; + if (r != OK) { + cpf_revoke(gid); - return(SUSPEND); + return r; } - /* No suspend, or cancelled suspend, so I/O is over and can be cleaned up. */ - if(safe) cpf_revoke(gid); + /* 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; - 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 dev_select(dev_t dev, int ops) +{ +/* 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 gen_io(driver_e, mess_ptr) -endpoint_t driver_e; /* which endpoint to call */ -message *mess_ptr; /* pointer to message for task */ +int dev_cancel(dev_t dev) { -/* 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. +/* 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 * *===========================================================================*/ diff --git a/servers/vfs/dmap.c b/servers/vfs/dmap.c index 3111c95b2..c6491fde8 100644 --- a/servers/vfs/dmap.c +++ b/servers/vfs/dmap.c @@ -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); diff --git a/servers/vfs/main.c b/servers/vfs/main.c index 41997836b..8a92df4c8 100644 --- a/servers/vfs/main.c +++ b/servers/vfs/main.c @@ -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(); diff --git a/servers/vfs/pipe.c b/servers/vfs/pipe.c index c0c896f93..50f6ddb3e 100644 --- a/servers/vfs/pipe.c +++ b/servers/vfs/pipe.c @@ -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); diff --git a/servers/vfs/proto.h b/servers/vfs/proto.h index ff0124f9e..8f1d16089 100644 --- a/servers/vfs/proto.h +++ b/servers/vfs/proto.h @@ -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); diff --git a/servers/vfs/read.c b/servers/vfs/read.c index 4ad64ab17..61fcd6de4 100644 --- a/servers/vfs/read.c +++ b/servers/vfs/read.c @@ -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"); diff --git a/servers/vfs/select.c b/servers/vfs/select.c index 46a480de4..81f20e076 100644 --- a/servers/vfs/select.c +++ b/servers/vfs/select.c @@ -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 * *===========================================================================*/