diff --git a/servers/avfs/comm.c b/servers/avfs/comm.c index 85b6d2f49..89b2e503c 100644 --- a/servers/avfs/comm.c +++ b/servers/avfs/comm.c @@ -49,6 +49,22 @@ PUBLIC void send_work(void) fs_sendmore(vmp); } +/*===========================================================================* + * fs_cancel * + *===========================================================================*/ +PUBLIC void fs_cancel(struct vmnt *vmp) +{ +/* Cancel all pending requests for this vmp */ + struct worker_thread *worker; + + while ((worker = vmp->m_comm.c_req_queue) != NULL) { + vmp->m_comm.c_req_queue = worker->w_next; + worker->w_next = NULL; + sending--; + worker_stop(worker); + } +} + /*===========================================================================* * fs_sendmore * *===========================================================================*/ @@ -80,8 +96,10 @@ PUBLIC int fs_sendrec(endpoint_t fs_e, message *reqmp) struct vmnt *vmp; int r; - if ((vmp = find_vmnt(fs_e)) == NULL) - panic("Trying to talk to non-existent FS"); + if ((vmp = find_vmnt(fs_e)) == NULL) { + printf("Trying to talk to non-existent FS endpoint %d\n", fs_e); + return(EIO); + } if (fs_e == fp->fp_endpoint) return(EDEADLK); if (!force_sync) { diff --git a/servers/avfs/device.c b/servers/avfs/device.c index 29130df29..969ac8b7d 100644 --- a/servers/avfs/device.c +++ b/servers/avfs/device.c @@ -990,7 +990,7 @@ PUBLIC void cdev_up(int maj) fd_nr); rfilp = rfp->fp_filp[fd_nr]; vp = rfilp->filp_vno; - if (!vp) panic("VFS: restart_reopen: no vp"); + if (!vp) panic("VFS: cdev_up: no vp"); if ((vp->v_mode & I_TYPE) != I_CHAR_SPECIAL) continue; if (major(vp->v_sdev) != maj) continue; @@ -1051,7 +1051,7 @@ int maj; if (!(rfilp->filp_flags & O_REOPEN)) { /* File descriptor is to be closed when driver restarts. */ - n = invalidate(rfilp); + n = invalidate_filp(rfilp); if (n != rfilp->filp_count) { printf("VFS: warning: invalidate/count " "discrepancy (%d, %d)\n", n, rfilp->filp_count); @@ -1064,7 +1064,7 @@ int maj; if (r == OK) return; /* Device could not be reopened. Invalidate all filps on that device.*/ - n = invalidate(rfilp); + n = invalidate_filp(rfilp); if (n != rfilp->filp_count) { printf("VFS: warning: invalidate/count " "discrepancy (%d, %d)\n", n, rfilp->filp_count); diff --git a/servers/avfs/filedes.c b/servers/avfs/filedes.c index 83a432c1b..681030623 100644 --- a/servers/avfs/filedes.c +++ b/servers/avfs/filedes.c @@ -201,18 +201,18 @@ PUBLIC struct filp *find_filp(struct vnode *vp, mode_t bits) } /*===========================================================================* - * invalidate * + * invalidate_filp * *===========================================================================*/ -PUBLIC int invalidate(struct filp *fp) +PUBLIC int invalidate_filp(struct filp *rfilp) { /* Invalidate filp. fp_filp_inuse is not cleared, so filp can't be reused until it is closed first. */ 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] == fp) { + 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++; } @@ -222,6 +222,21 @@ PUBLIC int invalidate(struct filp *fp) return(n); /* Report back how often this filp has been invalidated. */ } +/*===========================================================================* + * invalidate_filp_by_endpt * + *===========================================================================*/ +PUBLIC void invalidate_filp_by_endpt(endpoint_t proc_e) +{ + struct filp *f; + + 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); + } + } +} + /*===========================================================================* * lock_filp * *===========================================================================*/ diff --git a/servers/avfs/misc.c b/servers/avfs/misc.c index 31a8af2b8..ed866016b 100644 --- a/servers/avfs/misc.c +++ b/servers/avfs/misc.c @@ -450,6 +450,13 @@ PRIVATE void free_proc(struct fproc *exiter, int flags) (void) close_fd(exiter, i); } + /* Release root and working directories. */ + if (exiter->fp_rd) { put_vnode(exiter->fp_rd); exiter->fp_rd = NULL; } + if (exiter->fp_wd) { put_vnode(exiter->fp_wd); exiter->fp_wd = NULL; } + + /* The rest of these actions is only done when processes actually exit. */ + if (!(flags & FP_EXITING)) return; + /* Check if any process is SUSPENDed on this driver. * If a driver exits, unmap its entries in the dmap table. * (unmapping has to be done after the first step, because the @@ -457,14 +464,10 @@ PRIVATE void free_proc(struct fproc *exiter, int flags) */ unsuspend_by_endpt(exiter->fp_endpoint); dmap_unmap_by_endpt(exiter->fp_endpoint); - worker_stop_by_endpt(exiter->fp_endpoint); - /* Release root and working directories. */ - if (exiter->fp_rd) { put_vnode(exiter->fp_rd); exiter->fp_rd = NULL; } - if (exiter->fp_wd) { put_vnode(exiter->fp_wd); exiter->fp_wd = NULL; } - - /* The rest of these actions is only done when processes actually exit. */ - if (!(flags & FP_EXITING)) return; + worker_stop_by_endpt(exiter->fp_endpoint); /* Unblock waiting threads */ + vmnt_unmap_by_endpt(exiter->fp_endpoint); /* Invalidate open files if this + * was an active FS */ /* Invalidate endpoint number for error and sanity checks. */ exiter->fp_endpoint = NONE; diff --git a/servers/avfs/path.c b/servers/avfs/path.c index 2ac2eece0..d33f711a8 100644 --- a/servers/avfs/path.c +++ b/servers/avfs/path.c @@ -210,6 +210,11 @@ struct fproc *rfp; struct vmnt *vmp; vmp = find_vmnt(start_dir->v_fs_e); + if (vmp == NULL) { + r = EIO; + res_vp = NULL; + break; + } r = lock_vmnt(vmp, resolve->l_vmnt_lock); if (r == EDEADLK) { res_vp = NULL; @@ -390,6 +395,8 @@ struct fproc *rfp; dir_ino = start_node->v_inode_nr; vmpres = find_vmnt(fs_e); + if (vmpres == NULL) return(EIO); /* mountpoint vanished? */ + /* Is the process' root directory on the same partition?, * if so, set the chroot directory too. */ if (rfp->fp_rd->v_dev == rfp->fp_wd->v_dev) @@ -500,6 +507,7 @@ struct fproc *rfp; /* Unlock a previously locked vmnt if locked and lock new vmnt */ if (vmpres) unlock_vmnt(vmpres); vmpres = find_vmnt(fs_e); + if (vmpres == NULL) return(EIO); /* mount point vanished? */ if ((r = lock_vmnt(vmpres, resolve->l_vmnt_lock)) != OK) { if (r == EBUSY) vmpres = NULL; /* Already locked */ diff --git a/servers/avfs/proto.h b/servers/avfs/proto.h index 54d4a9d0c..e0a815293 100644 --- a/servers/avfs/proto.h +++ b/servers/avfs/proto.h @@ -21,6 +21,7 @@ struct job; typedef struct filp * filp_id_t; /* comm.c */ +_PROTOTYPE(void fs_cancel, (struct vmnt *vmp) ); _PROTOTYPE(int fs_sendrec, (endpoint_t fs_e, message *reqm) ); _PROTOTYPE(void fs_sendmore, (struct vmnt *vmp) ); _PROTOTYPE(void send_work, (void) ); @@ -92,7 +93,8 @@ _PROTOTYPE( struct filp *get_filp2, (struct fproc *rfp, int fild, _PROTOTYPE( void lock_filp, (struct filp *filp, tll_access_t locktype) ); _PROTOTYPE( void unlock_filp, (struct filp *filp) ); _PROTOTYPE( void unlock_filps, (struct filp *filp1, struct filp *filp2) ); -_PROTOTYPE( int invalidate, (struct filp *) ); +_PROTOTYPE( int invalidate_filp, (struct filp *) ); +_PROTOTYPE( void invalidate_filp_by_endpt, (endpoint_t proc_e) ); _PROTOTYPE( int do_verify_fd, (void) ); _PROTOTYPE( int set_filp, (filp_id_t sfilp) ); _PROTOTYPE( int do_set_filp, (void) ); @@ -334,6 +336,7 @@ _PROTOTYPE( struct vmnt *get_locked_vmnt, (struct fproc *rfp) ); _PROTOTYPE( void init_vmnts, (void) ); _PROTOTYPE( int lock_vmnt, (struct vmnt *vp, tll_access_t locktype) ); _PROTOTYPE( void unlock_vmnt, (struct vmnt *vp) ); +_PROTOTYPE( void vmnt_unmap_by_endpt, (endpoint_t proc_e) ); /* vnode.c */ _PROTOTYPE( void check_vnode_locks, (void) ); diff --git a/servers/avfs/vmnt.c b/servers/avfs/vmnt.c index 66c405678..a762421f3 100644 --- a/servers/avfs/vmnt.c +++ b/servers/avfs/vmnt.c @@ -159,6 +159,21 @@ PUBLIC int lock_vmnt(struct vmnt *vmp, tll_access_t locktype) return(OK); } +/*===========================================================================* + * vmnt_unmap_by_endpoint * + *===========================================================================*/ +PUBLIC void vmnt_unmap_by_endpt(endpoint_t proc_e) +{ + struct vmnt *vmp; + + if ((vmp = find_vmnt(proc_e)) != NULL) { + fs_cancel(vmp); + invalidate_filp_by_endpt(proc_e); + put_vnode(vmp->m_mounted_on); + clear_vmnt(vmp); + } +} + /*===========================================================================* * unlock_vmnt * *===========================================================================*/