diff --git a/commands/playwave/playwave.c b/commands/playwave/playwave.c index 53b92d8dc..28bdbf588 100644 --- a/commands/playwave/playwave.c +++ b/commands/playwave/playwave.c @@ -66,15 +66,36 @@ void usage() exit(-1); } +int open_audio(unsigned int *fragment_size, unsigned int channels, + unsigned int samples_per_sec, unsigned int bits) +{ + unsigned int sign; + int audio; + + /* Open DSP */ + if ((audio = open("/dev/audio", O_RDWR | O_REOPEN)) < 0) + { + printf("Cannot open /dev/audio: %s\n", strerror(errno)); + exit(-1); + } + + ioctl(audio, DSPIOMAX, fragment_size); /* Get maximum fragment size. */ + + /* Set DSP parameters (should check return values..) */ + ioctl(audio, DSPIOSIZE, fragment_size); /* Use max. fragment size. */ + ioctl(audio, DSPIOSTEREO, &channels); + ioctl(audio, DSPIORATE, &samples_per_sec); + ioctl(audio, DSPIOBITS, &bits); + sign = (bits == 16 ? 1 : 0); + ioctl(audio, DSPIOSIGN, &sign); + return audio; +} int main ( int argc, char *argv[] ) { int i, r, audio, file; char *buffer, *file_name = NULL; - unsigned int sign; - unsigned int fragment_size; - unsigned int channels; - unsigned int bits; + unsigned int fragment_size, fragment_size2; long data_pos; int showinfo = 0; @@ -91,22 +112,6 @@ int main ( int argc, char *argv[] ) } else file_name = argv[1]; - /* Open DSP */ - if ((audio = open("/dev/audio", O_RDWR | O_REOPEN)) < 0) - { - printf("Cannot open /dev/audio: %s\n", strerror(errno)); - exit(-1); - } - - /* Get maximum fragment size and try to allocate a buffer */ - ioctl(audio, DSPIOMAX, &fragment_size); - if ((buffer = malloc(fragment_size)) == (char *)0) - { - fprintf(stderr, "Cannot allocate buffer\n"); - exit(-1); - } - ioctl(audio, DSPIOSIZE, &fragment_size); - /* Open wav file */ if((file = open(file_name, O_RDONLY)) < 0) { @@ -141,15 +146,15 @@ int main ( int argc, char *argv[] ) exit(1); } - /* Set DSP parameters */ - channels = c_fields.Channels; - channels--; - bits = s_fields.BitsPerSample; - ioctl(audio, DSPIOSTEREO, &channels); - ioctl(audio, DSPIORATE, &c_fields.SamplesPerSec); - ioctl(audio, DSPIOBITS, &bits); - sign = (bits == 16 ? 1 : 0); - ioctl(audio, DSPIOSIGN, &sign); + /* Open audio device and set DSP parameters */ + audio = open_audio(&fragment_size, c_fields.Channels - 1, + c_fields.SamplesPerSec, s_fields.BitsPerSample); + + if ((buffer = malloc(fragment_size)) == (char *)0) + { + fprintf(stderr, "Cannot allocate buffer\n"); + exit(-1); + } /* Goto data chunk */ lseek(file, data_pos, SEEK_SET); @@ -203,6 +208,20 @@ int main ( int argc, char *argv[] ) { fprintf(stderr, "playwave: write to audio device failed: %s\n", strerror(errno)); + + /* If we get EIO, the driver might have restarted. Reopen the + * audio device. + */ + if (errno == EIO) { + close(audio); + audio = open_audio(&fragment_size2, + c_fields.Channels - 1, c_fields.SamplesPerSec, + s_fields.BitsPerSample); + if (fragment_size2 != fragment_size) { + fprintf(stderr, "Fragment size has changed\n"); + exit(1); + } + } } else { diff --git a/include/minix/com.h b/include/minix/com.h index 94faed468..2cf810573 100644 --- a/include/minix/com.h +++ b/include/minix/com.h @@ -198,7 +198,6 @@ #define DEV_OPEN (DEV_RQ_BASE + 6) /* open a minor device */ #define DEV_CLOSE (DEV_RQ_BASE + 7) /* close a minor device */ #define DEV_SELECT (DEV_RQ_BASE + 12) /* request select() attention */ -#define DEV_REOPEN (DEV_RQ_BASE + 14) /* reopen a minor device */ #define DEV_READ_S (DEV_RQ_BASE + 20) /* (safecopy) read from minor */ #define DEV_WRITE_S (DEV_RQ_BASE + 21) /* (safecopy) write to minor */ @@ -209,7 +208,6 @@ #define IS_DEV_RQ(type) (((type) & ~0xff) == DEV_RQ_BASE) #define DEV_REVIVE (DEV_RS_BASE + 2) /* driver revives process */ -#define DEV_REOPEN_REPL (DEV_RS_BASE + 5) /* reply to DEV_REOPEN */ #define DEV_CLOSE_REPL (DEV_RS_BASE + 6) /* reply to DEV_CLOSE */ #define DEV_SEL_REPL1 (DEV_RS_BASE + 7) /* first reply to DEV_SELECT */ #define DEV_SEL_REPL2 (DEV_RS_BASE + 8) /* (opt) second reply to DEV_SELECT */ diff --git a/lib/libchardriver/chardriver.c b/lib/libchardriver/chardriver.c index 4e723e6e1..cf34dd9f3 100644 --- a/lib/libchardriver/chardriver.c +++ b/lib/libchardriver/chardriver.c @@ -228,12 +228,6 @@ static void chardriver_reply(message *mess, int ipc_status, int r) reply_mess.REP_STATUS = r; break; - case DEV_REOPEN: - reply_mess.m_type = DEV_REOPEN_REPL; - reply_mess.REP_ENDPT = mess->USER_ENDPT; - reply_mess.REP_STATUS = r; - break; - case DEV_CLOSE: reply_mess.m_type = DEV_CLOSE_REPL; reply_mess.REP_ENDPT = mess->USER_ENDPT; @@ -266,7 +260,7 @@ static void chardriver_reply(message *mess, int ipc_status, int r) /*===========================================================================* * do_open * *===========================================================================*/ -static int do_open(struct chardriver *cdp, message *m_ptr, int is_reopen) +static int do_open(struct chardriver *cdp, message *m_ptr) { /* Open a minor device. */ endpoint_t user_endpt; @@ -280,7 +274,7 @@ static int do_open(struct chardriver *cdp, message *m_ptr, int is_reopen) /* Call the open hook. */ minor = m_ptr->DEVICE; access = m_ptr->COUNT; - user_endpt = is_reopen ? NONE : m_ptr->USER_ENDPT; /* XXX FIXME */ + user_endpt = m_ptr->USER_ENDPT; r = cdp->cdr_open(minor, access, user_endpt); @@ -481,7 +475,7 @@ void chardriver_process(struct chardriver *cdp, message *m_ptr, int ipc_status) */ if (IS_DEV_RQ(m_ptr->m_type) && !is_open_dev(m_ptr->DEVICE)) { /* Ignore spurious requests for unopened devices. */ - if (m_ptr->m_type != DEV_OPEN && m_ptr->m_type != DEV_REOPEN) + if (m_ptr->m_type != DEV_OPEN) return; /* do not send a reply */ /* Mark the device as opened otherwise. */ @@ -490,8 +484,7 @@ void chardriver_process(struct chardriver *cdp, message *m_ptr, int ipc_status) /* Call the appropriate function(s) for this request. */ switch (m_ptr->m_type) { - case DEV_OPEN: r = do_open(cdp, m_ptr, FALSE); break; - case DEV_REOPEN: r = do_open(cdp, m_ptr, TRUE); break; + case DEV_OPEN: r = do_open(cdp, m_ptr); break; case DEV_CLOSE: r = do_close(cdp, m_ptr); break; case DEV_READ_S: r = do_transfer(cdp, m_ptr, FALSE); break; case DEV_WRITE_S: r = do_transfer(cdp, m_ptr, TRUE); break; diff --git a/servers/vfs/README b/servers/vfs/README index 6c91f6687..c2a3d3549 100644 --- a/servers/vfs/README +++ b/servers/vfs/README @@ -149,11 +149,10 @@ normal and PM work is the responsibility of the worker thread infrastructure. There are several special tasks that require a worker thread, and these are implemented as normal work associated with a certain special process that does not make regular VFS calls anyway. For example, the initial ramdisk mount -procedure and the post-crash filp garbage collector use a thread associated -with the VFS process. Some of these special tasks require protection against -being started multiple times at once, as this is not only undesirable but also -disallowed. The full list of worker thread task types and subtypes is shown in -Table 1. +procedure uses a thread associated with the VFS process. Some of these special +tasks require protection against being started multiple times at once, as this +is not only undesirable but also disallowed. The full list of worker thread +task types and subtypes is shown in Table 1. {{{ ------------------------------------------------------------------------- @@ -167,8 +166,6 @@ Table 1. +---------------------------+--------+-----------------+----------------+ | DS event notification | normal | DS | yes | +---------------------------+--------+-----------------+----------------+ -| filp garbage collection | normal | VFS | no | -+---------------------------+--------+-----------------+----------------+ | initial ramdisk mounting | normal | VFS | no | +---------------------------+--------+-----------------+----------------+ | reboot sequence | normal | PM | no | @@ -677,15 +674,15 @@ a request. VFS does this with an arbitrary maximum of 5 attempts. === Recovery from character driver crashes === ## 5.2 Recovery from character driver crashes -Character special files are treated differently. Once VFS has found out a -driver has been restarted, it will stop the current request (if there is -any). It makes no sense to retry requests due to the nature of character -special files. If a character special driver can restart without changing -endpoints, this merely results in the current request (e.g., read, write, or -ioctl) failing and allows the user process to reissue the same request. On -the other hand, if a driver restart causes the driver to change endpoint -number, all associated file descriptors are marked invalid and subsequent -operations on them will always fail with a bad file descriptor error. +While VFS used to support minimal recovery from character driver crashes, the +added complexity has so far proven to outweigh the benefits, especially since +such crash recovery can never be fully transparent: it depends entirely on the +character device as to whether repeating an I/O request makes sense at all. +Currently, all operations except close(2) on a file descriptor that identifies +a device on a crashed character driver, will result in an EIO error. It is up +to the application to reopen the character device and retry whatever it was +doing in the appropriate manner. In the future, automatic reopen and I/O +restart may be reintroduced for a limited subset of character drivers. === Recovery from File Server crashes === ## 5.3 Recovery from File Server crashes diff --git a/servers/vfs/device.c b/servers/vfs/device.c index 68afaecf3..dd498529b 100644 --- a/servers/vfs/device.c +++ b/servers/vfs/device.c @@ -3,7 +3,6 @@ * * The entry points in this file are: * dev_open: open a character device - * dev_reopen: reopen a character device after a driver crash * dev_close: close a character device * cdev_reply: process the result of a character driver request * bdev_open: open a block device @@ -44,8 +43,6 @@ 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, unsigned long size); -static void restart_reopen(devmajor_t major); -static void reopen_reply(message *m_ptr); static int dummyproc; @@ -73,34 +70,6 @@ int dev_open( } -/*===========================================================================* - * dev_reopen * - *===========================================================================*/ -int dev_reopen( - dev_t dev, /* device to open */ - int filp_no, /* filp to reopen for */ - int flags /* mode bits and flags */ -) -{ -/* Reopen a character device after a failing device driver. */ - devmajor_t major_dev; - struct dmap *dp; - int r; - - /* Determine the major device number and call the device class specific - * open/close routine. (This is the only routine that must check the device - * number for being in range. All others can trust this check.) - */ - major_dev = major(dev); - if (major_dev < 0 || major_dev >= NR_DEVICES) return(ENXIO); - dp = &dmap[major_dev]; - if (dp->dmap_driver == NONE) return(ENXIO); - r = (*dp->dmap_opcl)(DEV_REOPEN, dev, filp_no, flags); - if (r == SUSPEND) r = OK; - return(r); -} - - /*===========================================================================* * dev_close * *===========================================================================*/ @@ -317,8 +286,7 @@ int dev_io( void *buf, /* virtual address of the buffer */ off_t pos, /* byte position */ size_t bytes, /* how many bytes to transfer */ - int flags, /* special flags, like O_NONBLOCK */ - int suspend_reopen /* Just suspend the process */ + int flags /* special flags, like O_NONBLOCK */ ) { /* Initiate a read, write, or ioctl to a device. */ @@ -339,15 +307,6 @@ int dev_io( /* See if driver is roughly valid. */ if (dp->dmap_driver == NONE) return(ENXIO); - if (suspend_reopen) { - /* Suspend user. */ - fp->fp_grant = GRANT_INVALID; - fp->fp_ioproc = NONE; - wait_for(dp->dmap_driver); - fp->fp_flags |= FP_SUSP_REOPEN; - return(SUSPEND); - } - if(isokendpt(dp->dmap_driver, &dummyproc) != OK) { printf("VFS: dev_io: old driver for major %x (%d)\n", major_dev, dp->dmap_driver); @@ -427,7 +386,7 @@ static int cdev_clone(dev_t dev, endpoint_t proc_e, devminor_t new_minor) } lock_vnode(vp, VNODE_OPCL); - assert(FD_ISSET(scratch(fp).file.fd_nr, &fp->fp_filp_inuse)); + assert(fp->fp_filp[scratch(fp).file.fd_nr] != NULL); unlock_vnode(fp->fp_filp[scratch(fp).file.fd_nr]->filp_vno); put_vnode(fp->fp_filp[scratch(fp).file.fd_nr]->filp_vno); @@ -450,7 +409,7 @@ static int cdev_clone(dev_t dev, endpoint_t proc_e, devminor_t new_minor) * gen_opcl * *===========================================================================*/ int gen_opcl( - int op, /* operation, DEV_OPEN/DEV_REOPEN/DEV_CLOSE */ + int op, /* operation, DEV_OPEN or DEV_CLOSE */ dev_t dev, /* device to open or close */ endpoint_t proc_e, /* process to open/close for */ int flags /* mode bits and flags */ @@ -485,17 +444,15 @@ int gen_opcl( if (r != OK) return(r); - if (op == DEV_OPEN || op == DEV_CLOSE) { - /* Block the thread waiting for a reply. */ - fp->fp_task = dp->dmap_driver; - self->w_task = dp->dmap_driver; - self->w_drv_sendrec = &dev_mess; + /* Block the thread waiting for a reply. */ + fp->fp_task = dp->dmap_driver; + self->w_task = dp->dmap_driver; + self->w_drv_sendrec = &dev_mess; - worker_wait(); + worker_wait(); - self->w_task = NONE; - self->w_drv_sendrec = NULL; - } + self->w_task = NONE; + self->w_drv_sendrec = NULL; /* Return the result from the driver. */ return(dev_mess.REP_STATUS); @@ -589,7 +546,7 @@ int do_ioctl(message *UNUSED(m_out)) { /* Perform the ioctl(ls_fd, request, argx) system call */ unsigned long ioctlrequest; - int r = OK, suspend_reopen; + int r = OK; struct filp *f; register struct vnode *vp; dev_t dev; @@ -607,14 +564,13 @@ int do_ioctl(message *UNUSED(m_out)) } if (r == OK) { - suspend_reopen = (f->filp_state & FS_NEEDS_REOPEN); dev = (dev_t) vp->v_sdev; if (S_ISBLK(vp->v_mode)) r = bdev_ioctl(dev, who_e, ioctlrequest, argx); else r = dev_io(DEV_IOCTL_S, dev, who_e, argx, 0, - ioctlrequest, f->filp_flags, suspend_reopen); + ioctlrequest, f->filp_flags); } unlock_filp(f); @@ -924,31 +880,6 @@ void bdev_up(devmajor_t maj) } -/*===========================================================================* - * cdev_up * - *===========================================================================*/ -void cdev_up(devmajor_t maj) -{ - /* A new character device driver has been mapped in. - */ - int needs_reopen; - struct filp *rfilp; - struct vnode *vp; - - needs_reopen= FALSE; - for (rfilp = filp; rfilp < &filp[NR_FILPS]; rfilp++) { - if (rfilp->filp_count < 1 || !(vp = rfilp->filp_vno)) continue; - if (major(vp->v_sdev) != maj) continue; - if (!S_ISCHR(vp->v_mode)) continue; - - rfilp->filp_state |= FS_NEEDS_REOPEN; - needs_reopen = TRUE; - } - - if (needs_reopen) - restart_reopen(maj); -} - /*===========================================================================* * opcl_reply * *===========================================================================*/ @@ -1032,7 +963,6 @@ void cdev_reply(void) switch (call_nr) { case DEV_OPEN_REPL: case DEV_CLOSE_REPL: opcl_reply(&m_in); break; - case DEV_REOPEN_REPL: reopen_reply(&m_in); break; case DEV_REVIVE: task_reply(&m_in); break; case DEV_SEL_REPL1: select_reply1(m_in.m_source, m_in.DEV_MINOR, m_in.DEV_SEL_OPS); @@ -1070,157 +1000,3 @@ void bdev_reply(struct dmap *dp) wp->w_drv_sendrec = NULL; worker_signal(wp); } - -/*===========================================================================* - * filp_gc_thread * - *===========================================================================*/ -static void filp_gc_thread(void) -{ -/* Filp garbage collection thread function. Since new filps may be invalidated - * while the actual garbage collection procedure is running, we repeat the - * procedure until it can not find any more work to do. - */ - - while (do_filp_gc()) - /* simply repeat */; -} - -/*===========================================================================* - * restart_reopen * - *===========================================================================*/ -static void restart_reopen(devmajor_t maj) -{ - devmajor_t major_dev; - devminor_t minor_dev; - endpoint_t driver_e; - struct vnode *vp; - struct filp *rfilp; - struct fproc *rfp; - message m_out; - int n, r; - - memset(&m_out, 0, sizeof(m_out)); - - if (maj < 0 || maj >= NR_DEVICES) panic("VFS: out-of-bound major"); - - for (rfilp = filp; rfilp < &filp[NR_FILPS]; rfilp++) { - if (rfilp->filp_count < 1 || !(vp = rfilp->filp_vno)) continue; - if (!(rfilp->filp_state & FS_NEEDS_REOPEN)) continue; - if (!S_ISCHR(vp->v_mode)) continue; - - major_dev = major(vp->v_sdev); - minor_dev = minor(vp->v_sdev); - if (major_dev != maj) continue; - - if (rfilp->filp_flags & O_REOPEN) { - /* Try to reopen a file upon driver restart */ - r = dev_reopen(vp->v_sdev, rfilp-filp, - rfilp->filp_mode & (R_BIT|W_BIT)); - - if (r == OK) - return; - - printf("VFS: file on dev %d/%d re-open failed: %d\n", - major_dev, minor_dev, r); - } - - /* File descriptor is to be closed when driver restarts. */ - n = invalidate_filp(rfilp); - if (n != rfilp->filp_count) { - printf("VFS: warning: invalidate/count " - "discrepancy (%d, %d)\n", n, rfilp->filp_count); - } - rfilp->filp_count = 0; - - /* We have to clean up this filp and vnode, but can't do that yet as - * it's locked by a worker thread. Start a new job to garbage collect - * invalidated filps associated with this device driver. This thread - * is associated with a process that we know is idle otherwise: VFS. - * Be careful that we don't start two threads or lose work, though. - */ - if (worker_can_start(fproc_addr(VFS_PROC_NR))) { - worker_start(fproc_addr(VFS_PROC_NR), filp_gc_thread, - &m_out /*unused*/, FALSE /*use_spare*/); - } - } - - /* Nothing more to re-open. Restart suspended processes */ - driver_e = dmap[maj].dmap_driver; - for (rfp = &fproc[0]; rfp < &fproc[NR_PROCS]; rfp++) { - if(rfp->fp_pid == PID_FREE) continue; - if(rfp->fp_blocked_on == FP_BLOCKED_ON_OTHER && - rfp->fp_task == driver_e && (rfp->fp_flags & FP_SUSP_REOPEN)) { - rfp->fp_flags &= ~FP_SUSP_REOPEN; - rfp->fp_blocked_on = FP_BLOCKED_ON_NONE; - reply(&m_out, rfp->fp_endpoint, ERESTART); - } - } -} - - -/*===========================================================================* - * reopen_reply * - *===========================================================================*/ -static void reopen_reply(message *m_ptr) -{ - endpoint_t driver_e; - devmajor_t maj; - int filp_no, status; - struct filp *rfilp; - struct vnode *vp; - struct dmap *dp; - - driver_e = m_ptr->m_source; - filp_no = m_ptr->REP_ENDPT; - status = m_ptr->REP_STATUS; - - if (filp_no < 0 || filp_no >= NR_FILPS) { - printf("VFS: reopen_reply: bad filp number %d from driver %d\n", - filp_no, driver_e); - return; - } - - rfilp = &filp[filp_no]; - if (rfilp->filp_count < 1) { - printf("VFS: reopen_reply: filp number %d not inuse (from driver %d)\n", - filp_no, driver_e); - return; - } - - vp = rfilp->filp_vno; - if (!vp) { - printf("VFS: reopen_reply: no vnode for filp number %d (from driver " - "%d)\n", filp_no, driver_e); - return; - } - - if (!(rfilp->filp_state & FS_NEEDS_REOPEN)) { - printf("VFS: reopen_reply: bad state %d for filp number %d" - " (from driver %d)\n", rfilp->filp_state, filp_no, driver_e); - return; - } - - if (!S_ISCHR(vp->v_mode)) { - printf("VFS: reopen_reply: bad mode 0%o for filp number %d" - " (from driver %d)\n", vp->v_mode, filp_no, driver_e); - return; - } - - maj = major(vp->v_sdev); - dp = &dmap[maj]; - if (dp->dmap_driver != driver_e) { - printf("VFS: reopen_reply: bad major %d for filp number %d " - "(from driver %d, current driver is %d)\n", maj, filp_no, - driver_e, dp->dmap_driver); - return; - } - - if (status == OK) { - rfilp->filp_state &= ~FS_NEEDS_REOPEN; - } else { - printf("VFS: reopen_reply: should handle error status\n"); - return; - } - - restart_reopen(maj); -} diff --git a/servers/vfs/dmap.c b/servers/vfs/dmap.c index b96724c04..54d071754 100644 --- a/servers/vfs/dmap.c +++ b/servers/vfs/dmap.c @@ -359,7 +359,7 @@ void dmap_endpt_up(endpoint_t proc_e, int is_blk) worker = worker_get(dp->dmap_servicing); worker_stop(worker); } - cdev_up(major); + invalidate_filp_by_char_major(major); } } } diff --git a/servers/vfs/exec.c b/servers/vfs/exec.c index 51881b24b..d8e374521 100644 --- a/servers/vfs/exec.c +++ b/servers/vfs/exec.c @@ -325,7 +325,6 @@ int pm_exec(vir_bytes path, size_t path_len, vir_bytes frame, size_t frame_len, newfilp->filp_count = 1; newfilp->filp_vno = vp; newfilp->filp_flags = O_RDONLY; - FD_SET(newfd, &vmfp->fp_filp_inuse); vmfp->fp_filp[newfd] = newfilp; /* dup_vnode(vp); */ execi.vmfd = newfd; diff --git a/servers/vfs/file.h b/servers/vfs/file.h index 022aa4652..1bba747ab 100644 --- a/servers/vfs/file.h +++ b/servers/vfs/file.h @@ -8,7 +8,6 @@ EXTERN struct filp { mode_t filp_mode; /* RW bits, telling how file is opened */ int filp_flags; /* flags from open and fcntl */ - int filp_state; /* state for crash recovery */ int filp_count; /* how many file descriptors share this slot?*/ struct vnode *filp_vno; /* vnode belonging to this file */ off_t filp_pos; /* file position */ @@ -29,11 +28,7 @@ EXTERN struct filp { int filp_pipe_select_ops; } filp[NR_FILPS]; -#define FILP_CLOSED 0 /* filp_mode: associated device closed */ - -#define FS_NORMAL 000 /* file descriptor can be used normally */ -#define FS_NEEDS_REOPEN 001 /* file descriptor needs to be re-opened */ -#define FS_INVALIDATED 002 /* file was invalidated */ +#define FILP_CLOSED 0 /* filp_mode: associated device closed/gone */ #define FSF_UPDATE 001 /* The driver should be informed about new * state. diff --git a/servers/vfs/filedes.c b/servers/vfs/filedes.c index 865a66335..571abaf2c 100644 --- a/servers/vfs/filedes.c +++ b/servers/vfs/filedes.c @@ -75,64 +75,6 @@ void check_filp_locks(void) #endif } -/*===========================================================================* - * do_filp_gc * - *===========================================================================*/ -int do_filp_gc(void) -{ -/* Perform filp garbage collection. Return whether at least one invalidated - * filp was found, in which case the entire procedure will be invoked again. - */ - struct filp *f; - struct vnode *vp; - int found = FALSE; - - for (f = &filp[0]; f < &filp[NR_FILPS]; f++) { - if (!(f->filp_state & FS_INVALIDATED)) continue; - - found = TRUE; - - if (f->filp_mode == FILP_CLOSED || f->filp_vno == NULL) { - /* File was already closed before gc could kick in */ - assert(f->filp_count <= 0); - f->filp_state &= ~FS_INVALIDATED; - f->filp_count = 0; - continue; - } - - assert(f->filp_vno != NULL); - vp = f->filp_vno; - - /* Synchronize with worker thread that might hold a lock on the vp */ - lock_vnode(vp, VNODE_OPCL); - unlock_vnode(vp); - - /* If garbage collection was invoked due to a failed device open - * request, then common_open has already cleaned up and we have - * nothing to do. - */ - if (!(f->filp_state & FS_INVALIDATED)) { - continue; - } - - /* If garbage collection was invoked due to a failed device close - * request, the close_filp has already cleaned up and we have nothing - * to do. - */ - if (f->filp_mode != FILP_CLOSED) { - assert(f->filp_count == 0); - f->filp_count = 1; /* So lock_filp and close_filp will do - * their job */ - lock_filp(f, VNODE_READ); - close_filp(f); - } - - f->filp_state &= ~FS_INVALIDATED; - } - - return found; -} - /*===========================================================================* * init_filps * *===========================================================================*/ @@ -163,7 +105,7 @@ int get_fd(struct fproc *rfp, int start, mode_t bits, int *k, struct filp **fpt) /* Search the fproc fp_filp table for a free file descriptor. */ for (i = start; i < OPEN_MAX; i++) { - if (rfp->fp_filp[i] == NULL && !FD_ISSET(i, &rfp->fp_filp_inuse)) { + if (rfp->fp_filp[i] == NULL) { /* A file descriptor has been located. */ *k = i; break; @@ -186,7 +128,6 @@ int get_fd(struct fproc *rfp, int start, mode_t bits, int *k, struct filp **fpt) f->filp_select_ops = 0; f->filp_pipe_select_ops = 0; f->filp_flags = 0; - f->filp_state = FS_NORMAL; f->filp_select_flags = 0; f->filp_softlock = NULL; *fpt = f; @@ -226,9 +167,9 @@ tll_access_t locktype; filp = NULL; if (fild < 0 || fild >= OPEN_MAX) err_code = EBADF; - else if (rfp->fp_filp[fild] == NULL && FD_ISSET(fild, &rfp->fp_filp_inuse)) - err_code = EIO; /* The filedes is not there, but is not closed either. - */ + else if (locktype != VNODE_OPCL && rfp->fp_filp[fild] != NULL && + rfp->fp_filp[fild]->filp_mode == FILP_CLOSED) + err_code = EIO; /* disallow all use except close(2) */ else if ((filp = rfp->fp_filp[fild]) == NULL) err_code = EBADF; else @@ -265,24 +206,11 @@ struct filp *find_filp(struct vnode *vp, mode_t bits) /*===========================================================================* * invalidate_filp * *===========================================================================*/ -int invalidate_filp(struct filp *rfilp) +void invalidate_filp(struct filp *rfilp) { -/* Invalidate filp. fp_filp_inuse is not cleared, so filp can't be reused - until it is closed first. */ +/* Invalidate filp. */ - int f, fd, n = 0; - for (f = 0; f < NR_PROCS; f++) { - if (fproc[f].fp_pid == PID_FREE) continue; - for (fd = 0; fd < OPEN_MAX; fd++) { - if(fproc[f].fp_filp[fd] && fproc[f].fp_filp[fd] == rfilp) { - fproc[f].fp_filp[fd] = NULL; - n++; - } - } - } - - rfilp->filp_state |= FS_INVALIDATED; - return(n); /* Report back how often this filp has been invalidated. */ + rfilp->filp_mode = FILP_CLOSED; } /*===========================================================================* @@ -296,7 +224,7 @@ void invalidate_filp_by_char_major(int major) if (f->filp_count != 0 && f->filp_vno != NULL) { if (major(f->filp_vno->v_sdev) == major && S_ISCHR(f->filp_vno->v_mode)) { - (void) invalidate_filp(f); + invalidate_filp(f); } } } @@ -312,7 +240,7 @@ void invalidate_filp_by_endpt(endpoint_t proc_e) for (f = &filp[0]; f < &filp[NR_FILPS]; f++) { if (f->filp_count != 0 && f->filp_vno != NULL) { if (f->filp_vno->v_fs_e == proc_e) - (void) invalidate_filp(f); + invalidate_filp(f); } } } @@ -372,7 +300,7 @@ struct filp *filp; if (filp->filp_softlock != NULL) assert(filp->filp_softlock == fp); - if (filp->filp_count > 0 || filp->filp_state & FS_INVALIDATED) { + if (filp->filp_count > 0) { /* Only unlock vnode if filp is still in use */ /* and if we don't hold a soft lock */ @@ -507,11 +435,8 @@ filp_id_t cfilp; /* Find an open slot in fp_filp */ for (fd = 0; fd < OPEN_MAX; fd++) { - if (rfp->fp_filp[fd] == NULL && - !FD_ISSET(fd, &rfp->fp_filp_inuse)) { - + if (rfp->fp_filp[fd] == NULL) { /* Found a free slot, add descriptor */ - FD_SET(fd, &rfp->fp_filp_inuse); rfp->fp_filp[fd] = cfilp; rfp->fp_filp[fd]->filp_count++; return(fd); @@ -586,7 +511,6 @@ int fd; rfilp = (struct filp *) verify_fd(ep, fd); if (rfilp != NULL) { /* Found a valid descriptor, remove it */ - FD_CLR(fd, &rfp->fp_filp_inuse); if (rfp->fp_filp[fd]->filp_count == 0) { unlock_filp(rfilp); printf("VFS: filp_count for slot %d fd %d already zero", slot, @@ -653,15 +577,9 @@ struct filp *f; } unlock_bsf(); - /* Attempt to close only when feasible */ - if (!(f->filp_state & FS_INVALIDATED)) { - (void) bdev_close(dev); /* Ignore errors */ - } + (void) bdev_close(dev); /* Ignore errors */ } else { - /* Attempt to close only when feasible */ - if (!(f->filp_state & FS_INVALIDATED)) { - (void) dev_close(dev); /* Ignore errors */ - } + (void) dev_close(dev); /* Ignore errors */ } f->filp_mode = FILP_CLOSED; @@ -674,10 +592,7 @@ struct filp *f; release(vp, rw, susp_count); } - f->filp_count--; /* If filp got invalidated at device closure, the - * count might've become negative now */ - if (f->filp_count == 0 || - (f->filp_count < 0 && f->filp_state & FS_INVALIDATED)) { + if (--f->filp_count == 0) { if (S_ISFIFO(vp->v_mode)) { /* Last reader or writer is going. Tell PFS about latest * pipe size. diff --git a/servers/vfs/fproc.h b/servers/vfs/fproc.h index 444d99968..097bcfaae 100644 --- a/servers/vfs/fproc.h +++ b/servers/vfs/fproc.h @@ -20,8 +20,7 @@ EXTERN struct fproc { struct vnode *fp_wd; /* working directory; NULL during reboot */ struct vnode *fp_rd; /* root directory; NULL during reboot */ - struct filp *fp_filp[OPEN_MAX];/* the file descriptor table */ - fd_set fp_filp_inuse; /* which fd's are in use? */ + struct filp *fp_filp[OPEN_MAX];/* the file descriptor table (free if NULL) */ fd_set fp_cloexec_set; /* bit map for POSIX Table 6-2 FD_CLOEXEC */ dev_t fp_tty; /* major/minor of controlling tty */ @@ -59,16 +58,13 @@ EXTERN struct fproc { } fproc[NR_PROCS]; /* fp_flags */ -#define FP_NOFLAGS 00 -#define FP_SUSP_REOPEN 01 /* Process is suspended until the reopens are - * completed (after the restart of a driver). - */ +#define FP_NOFLAGS 0000 +#define FP_SRV_PROC 0001 /* Set if process is a service */ #define FP_REVIVED 0002 /* Indicates process is being revived */ #define FP_SESLDR 0004 /* Set if process is session leader */ #define FP_PENDING 0010 /* Set if process has pending work */ #define FP_EXITING 0020 /* Set if process is exiting */ #define FP_PM_WORK 0040 /* Set if process has a postponed PM request */ -#define FP_SRV_PROC 0100 /* Set if process is a service */ /* Field values. */ #define NOT_REVIVING 0xC0FFEEE /* process is not being revived */ diff --git a/servers/vfs/main.c b/servers/vfs/main.c index 7e9087942..56374d78c 100644 --- a/servers/vfs/main.c +++ b/servers/vfs/main.c @@ -389,7 +389,8 @@ static int sef_cb_init_fresh(int UNUSED(type), sef_init_info_t *info) /* Initialize process directories. mount_fs will set them to the * correct values. */ - FD_ZERO(&(rfp->fp_filp_inuse)); + for (i = 0; i < OPEN_MAX; i++) + rfp->fp_filp[i] = NULL; rfp->fp_rd = NULL; rfp->fp_wd = NULL; } diff --git a/servers/vfs/misc.c b/servers/vfs/misc.c index e167c17a9..449b366e6 100644 --- a/servers/vfs/misc.c +++ b/servers/vfs/misc.c @@ -121,7 +121,6 @@ int do_fcntl(message *UNUSED(m_out)) else if ((r = get_fd(fp, fcntl_argx, 0, &new_fd, NULL)) == OK) { f->filp_count++; fp->fp_filp[new_fd] = f; - FD_SET(new_fd, &fp->fp_filp_inuse); r = new_fd; } break; @@ -337,9 +336,6 @@ int dupvm(struct fproc *rfp, int pfd, int *vmfd, struct filp **newfilp) assert(f->filp_count > 0); vmf->fp_filp[procfd] = f; - /* mmap FD's are inuse */ - FD_SET(procfd, &vmf->fp_filp_inuse); - *newfilp = f; return OK; diff --git a/servers/vfs/open.c b/servers/vfs/open.c index 6587c5371..2beb489f6 100644 --- a/servers/vfs/open.c +++ b/servers/vfs/open.c @@ -127,7 +127,6 @@ int common_open(char path[PATH_MAX], int oflags, mode_t omode) /* Claim the file descriptor and filp slot and fill them in. */ fp->fp_filp[scratch(fp).file.fd_nr] = filp; - FD_SET(scratch(fp).file.fd_nr, &fp->fp_filp_inuse); filp->filp_count = 1; filp->filp_vno = vp; filp->filp_flags = oflags; @@ -267,10 +266,8 @@ int common_open(char path[PATH_MAX], int oflags, mode_t omode) if (r != OK) { if (r != SUSPEND) { fp->fp_filp[scratch(fp).file.fd_nr] = NULL; - FD_CLR(scratch(fp).file.fd_nr, &fp->fp_filp_inuse); filp->filp_count = 0; filp->filp_vno = NULL; - filp->filp_state &= ~FS_INVALIDATED; /* Prevent garbage col. */ put_vnode(vp); } } else { @@ -687,7 +684,6 @@ int fd_nr; close_filp(rfilp); FD_CLR(fd_nr, &rfp->fp_cloexec_set); - FD_CLR(fd_nr, &rfp->fp_filp_inuse); /* Check to see if the file is locked. If so, release all locks. */ if (nr_locks > 0) { diff --git a/servers/vfs/pipe.c b/servers/vfs/pipe.c index 57c2378b8..88da3ef7c 100644 --- a/servers/vfs/pipe.c +++ b/servers/vfs/pipe.c @@ -105,11 +105,9 @@ static int create_pipe(int fil_des[2], int flags) return(r); } rfp->fp_filp[fil_des[0]] = fil_ptr0; - FD_SET(fil_des[0], &rfp->fp_filp_inuse); fil_ptr0->filp_count = 1; /* mark filp in use */ if ((r = get_fd(fp, 0, W_BIT, &fil_des[1], &fil_ptr1)) != OK) { rfp->fp_filp[fil_des[0]] = NULL; - FD_CLR(fil_des[0], &rfp->fp_filp_inuse); fil_ptr0->filp_count = 0; /* mark filp free */ unlock_filp(fil_ptr0); unlock_vnode(vp); @@ -117,7 +115,6 @@ static int create_pipe(int fil_des[2], int flags) return(r); } rfp->fp_filp[fil_des[1]] = fil_ptr1; - FD_SET(fil_des[1], &rfp->fp_filp_inuse); fil_ptr1->filp_count = 1; /* Create a named pipe inode on PipeFS */ @@ -126,10 +123,8 @@ static int create_pipe(int fil_des[2], int flags) if (r != OK) { rfp->fp_filp[fil_des[0]] = NULL; - FD_CLR(fil_des[0], &rfp->fp_filp_inuse); fil_ptr0->filp_count = 0; rfp->fp_filp[fil_des[1]] = NULL; - FD_CLR(fil_des[1], &rfp->fp_filp_inuse); fil_ptr1->filp_count = 0; unlock_filp(fil_ptr1); unlock_filp(fil_ptr0); @@ -332,9 +327,6 @@ void suspend(int why) fp->fp_blocked_on = why; assert(fp->fp_grant == GRANT_INVALID || !GRANT_VALID(fp->fp_grant)); fp->fp_block_callnr = job_call_nr; - fp->fp_flags &= ~FP_SUSP_REOPEN; /* Clear this flag. The caller - * can set it when needed. - */ } /*===========================================================================* @@ -381,7 +373,7 @@ void unsuspend_by_endpt(endpoint_t proc_e) for (rp = &fproc[0]; rp < &fproc[NR_PROCS]; rp++) { if (rp->fp_pid == PID_FREE) continue; if (rp->fp_blocked_on == FP_BLOCKED_ON_OTHER && rp->fp_task == proc_e) - revive(rp->fp_endpoint, EAGAIN); + revive(rp->fp_endpoint, EIO); } /* Revive processes waiting in drivers on select()s with EAGAIN too */ @@ -436,8 +428,8 @@ int count; /* max number of processes to release */ if (rp->fp_blocked_on == FP_BLOCKED_ON_POPEN || rp->fp_blocked_on == FP_BLOCKED_ON_LOCK || rp->fp_blocked_on == FP_BLOCKED_ON_OTHER) { - if (!FD_ISSET(scratch(rp).file.fd_nr, - &rp->fp_filp_inuse)) + f = rp->fp_filp[scratch(rp).file.fd_nr]; + if (f == NULL || f->filp_mode == FILP_CLOSED) continue; if (rp->fp_filp[scratch(rp).file.fd_nr]->filp_vno != vp) continue; @@ -570,15 +562,6 @@ void unpause(void) break; case FP_BLOCKED_ON_OTHER:/* process trying to do device I/O (e.g. tty)*/ - if (fp->fp_flags & FP_SUSP_REOPEN) { - /* Process is suspended while waiting for a reopen. - * Just reply EINTR. - */ - fp->fp_flags &= ~FP_SUSP_REOPEN; - status = EINTR; - break; - } - fild = scratch(fp).file.fd_nr; if (fild < 0 || fild >= OPEN_MAX) panic("file descriptor out-of-range"); diff --git a/servers/vfs/proto.h b/servers/vfs/proto.h index 9f6a38616..d989429e5 100644 --- a/servers/vfs/proto.h +++ b/servers/vfs/proto.h @@ -30,14 +30,13 @@ void send_work(void); /* device.c */ int dev_open(dev_t dev, int flags); -int dev_reopen(dev_t dev, int filp_no, int flags); int dev_close(dev_t dev); void cdev_reply(void); int bdev_open(dev_t dev, int access); int bdev_close(dev_t dev); void bdev_reply(struct dmap *dp); 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 gen_opcl(int op, dev_t dev, endpoint_t task_nr, int flags); int gen_io(endpoint_t drv_e, message *mess_ptr); int no_dev(int op, dev_t dev, endpoint_t proc, int flags); @@ -51,7 +50,6 @@ 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); /* dmap.c */ void lock_dmap(struct dmap *dp); @@ -78,7 +76,6 @@ int pm_exec(vir_bytes path, size_t path_len, vir_bytes frame, size_t frame_len, vir_bytes *pc, vir_bytes *newsp, vir_bytes *ps_str, int flags); /* filedes.c */ -int do_filp_gc(void); void check_filp_locks(void); void check_filp_locks_by_me(void); void init_filps(void); @@ -90,7 +87,7 @@ struct filp *get_filp2(struct fproc *rfp, int fild, tll_access_t locktype); void lock_filp(struct filp *filp, tll_access_t locktype); void unlock_filp(struct filp *filp); void unlock_filps(struct filp *filp1, struct filp *filp2); -int invalidate_filp(struct filp *); +void invalidate_filp(struct filp *); void invalidate_filp_by_endpt(endpoint_t proc_e); void invalidate_filp_by_char_major(int major); int do_verify_fd(message *m_out); diff --git a/servers/vfs/read.c b/servers/vfs/read.c index fcd280aaf..1a43d4ad9 100644 --- a/servers/vfs/read.c +++ b/servers/vfs/read.c @@ -105,7 +105,7 @@ int actual_read_write_peek(struct fproc *rfp, int rw_flag, int io_fd, if (((f->filp_mode) & (ro ? R_BIT : W_BIT)) == 0) { unlock_filp(f); - return(f->filp_mode == FILP_CLOSED ? EIO : EBADF); + return(EBADF); } if (scratch(rfp).io.io_nbytes == 0) { unlock_filp(f); @@ -160,7 +160,6 @@ int read_write(struct fproc *rfp, int rw_flag, struct filp *f, r = rw_pipe(rw_flag, for_e, f, buf, size); } else if (S_ISCHR(vp->v_mode)) { /* Character special files. */ dev_t dev; - int suspend_reopen; int op = (rw_flag == READING ? DEV_READ_S : DEV_WRITE_S); if(rw_flag == PEEKING) { @@ -171,11 +170,9 @@ int read_write(struct fproc *rfp, int rw_flag, struct filp *f, if (vp->v_sdev == NO_DEV) panic("VFS: read_write tries to access char dev NO_DEV"); - suspend_reopen = (f->filp_state & FS_NEEDS_REOPEN); dev = (dev_t) vp->v_sdev; - r = dev_io(op, dev, for_e, buf, position, size, f->filp_flags, - suspend_reopen); + r = dev_io(op, dev, for_e, buf, position, size, f->filp_flags); if (r >= 0) { /* This should no longer happen: all calls are asynchronous. */ printf("VFS: I/O to device %x succeeded immediately!?\n", dev); diff --git a/servers/vfs/select.c b/servers/vfs/select.c index ace48a397..22f3c555a 100644 --- a/servers/vfs/select.c +++ b/servers/vfs/select.c @@ -752,7 +752,7 @@ void select_unsuspend_by_endpt(endpoint_t proc_e) major = major(f->filp_vno->v_sdev); if (dmap_driver_match(proc_e, major)) { se->filps[fd] = NULL; - se->error = EINTR; + se->error = EIO; select_cancel_filp(f); wakehim = 1; }