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 *
*===========================================================================*/
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) {
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;
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);
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);
}
/*===========================================================================*
- * 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++;
}
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 *
*===========================================================================*/
(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
*/
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;
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;
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)
/* 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 */
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) );
_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) );
_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) );
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 *
*===========================================================================*/