From: Thomas Veerman Date: Tue, 6 Sep 2011 10:11:18 +0000 (+0000) Subject: Make AVFS resilient against failing back calls X-Git-Tag: v3.2.0~317 X-Git-Url: http://zhaoyanbai.com/repos/%22http:/www.isc.org/icons/Bv9ARM.ch09.html?a=commitdiff_plain;h=7db039347a6fdb66f6a08f2cf16c06299b4acf08;p=minix.git Make AVFS resilient against failing back calls --- diff --git a/servers/avfs/comm.c b/servers/avfs/comm.c index b7254463a..06c08e49b 100644 --- a/servers/avfs/comm.c +++ b/servers/avfs/comm.c @@ -24,6 +24,7 @@ struct fproc *rfp; transid = rfp->fp_wtid + VFS_TRANSID; rfp->fp_sendrec->m_type = TRNS_ADD_ID(rfp->fp_sendrec->m_type, transid); + rfp->fp_task = vmp->m_fs_e; if ((r = asynsend3(vmp->m_fs_e, rfp->fp_sendrec, AMF_NOREPLY)) != OK) { printf("VFS: sendmsg: error sending message. " "FS_e: %d req_nr: %d err: %d\n", vmp->m_fs_e, diff --git a/servers/avfs/main.c b/servers/avfs/main.c index 2e548b80b..a47ea73c7 100644 --- a/servers/avfs/main.c +++ b/servers/avfs/main.c @@ -257,6 +257,7 @@ PRIVATE void *do_fs_reply(struct job *job) } *rfp->fp_sendrec = m_in; + rfp->fp_task = NONE; vmp->m_comm.c_cur_reqs--; /* We've got our reply, make room for others */ worker_signal(worker_get(rfp->fp_wtid));/* Continue this worker thread */ @@ -342,7 +343,7 @@ PRIVATE void *do_pending_pipe(void *arg) fp->fp_buffer, fp->fp_nbytes); if (r != SUSPEND) /* Do we have results to report? */ - reply(who_e, r); + (void) reply(who_e, r); unlock_filp(f); @@ -376,8 +377,10 @@ PUBLIC void *do_dummy(void *arg) *===========================================================================*/ PRIVATE void *do_work(void *arg) { - int error; + int error, i; struct job my_job; + struct fproc *rfp; + struct vmnt *vmp; my_job = *((struct job *) arg); fp = my_job.j_fp; @@ -422,14 +425,24 @@ PRIVATE void *do_work(void *arg) /* Copy the results back to the user and send reply. */ if (error != SUSPEND) { if (deadlock_resolving) { - struct vmnt *vmp; if ((vmp = find_vmnt(who_e)) != NULL) vmp->m_flags &= ~VMNT_BACKCALL; if (fp->fp_wtid == dl_worker.w_tid) deadlock_resolving = 0; } - reply(who_e, error ); + if (reply(who_e, error) != OK) { + if ((vmp = find_vmnt(who_e)) != NULL) { + for (i = 0; i < NR_PROCS; i++) { + rfp = &fproc[i]; + if (rfp->fp_task == vmp->m_fs_e) { + /* We found a process waiting for a + * reply from non-responsive FS */ + worker_stop(worker_get(rfp->fp_wtid)); + } + } + } + } } thread_cleanup(fp); @@ -751,7 +764,7 @@ PRIVATE void get_work() /*===========================================================================* * reply * *===========================================================================*/ -PUBLIC void reply(whom, result) +PUBLIC int reply(whom, result) int whom; /* process to reply to */ int result; /* result of the call (usually OK or error #) */ { @@ -762,8 +775,8 @@ int result; /* result of the call (usually OK or error #) */ r = sendnb(whom, &m_out); if (r != OK) { printf("VFS: couldn't send reply %d to %d: %d\n", result, whom, r); - panic("Yikes %d", call_nr); } + return(r); } /*===========================================================================* @@ -895,7 +908,8 @@ PRIVATE void service_pm() break; case PM_SETGROUPS: - pm_setgroups(m_in.PM_PROC, m_in.PM_GROUP_NO, m_in.PM_GROUP_ADDR); + pm_setgroups(m_in.PM_PROC, m_in.PM_GROUP_NO, + (gid_t *) m_in.PM_GROUP_ADDR); m_out.m_type = PM_SETGROUPS_REPLY; m_out.PM_PROC = m_in.PM_PROC; diff --git a/servers/avfs/mount.c b/servers/avfs/mount.c index 64f42407f..05e4ff0b2 100644 --- a/servers/avfs/mount.c +++ b/servers/avfs/mount.c @@ -222,8 +222,11 @@ char mount_label[LABEL_MAX] ) } else r = EBUSY; - if (vp != NULL) + if (vp != NULL) { + /* Quickly unlock to allow back calls (from e.g. FUSE) to + * relock */ unlock_vmnt(parent_vmp); + } if (r != OK) { if (vp != NULL) { diff --git a/servers/avfs/proto.h b/servers/avfs/proto.h index f7da182ec..54eb107a3 100644 --- a/servers/avfs/proto.h +++ b/servers/avfs/proto.h @@ -116,7 +116,7 @@ _PROTOTYPE( void lock_revive, (void) ); /* main.c */ _PROTOTYPE( int main, (void) ); -_PROTOTYPE( void reply, (int whom, int result) ); +_PROTOTYPE( int reply, (int whom, int result) ); _PROTOTYPE( void lock_proc, (struct fproc *rfp, int force_lock) ); _PROTOTYPE( void unlock_proc, (struct fproc *rfp) ); _PROTOTYPE( void *do_dummy, (void *arg) ); @@ -366,8 +366,9 @@ _PROTOTYPE( struct worker_thread *worker_get, (thread_t worker_tid) ); _PROTOTYPE( struct job *worker_getjob, (thread_t worker_tid) ); _PROTOTYPE( void worker_init, (struct worker_thread *worker) ); _PROTOTYPE( struct worker_thread *worker_self, (void) ); -_PROTOTYPE( void worker_start, (void *(*func)(void *arg)) ); _PROTOTYPE( void worker_signal, (struct worker_thread *worker) ); +_PROTOTYPE( void worker_start, (void *(*func)(void *arg)) ); +_PROTOTYPE( void worker_stop, (struct worker_thread *worker) ); _PROTOTYPE( void worker_wait, (void) ); _PROTOTYPE( void sys_worker_start, (void *(*func)(void *arg)) ); _PROTOTYPE( void dl_worker_start, (void *(*func)(void *arg)) ); diff --git a/servers/avfs/vnode.c b/servers/avfs/vnode.c index 5cd641780..ad854f732 100644 --- a/servers/avfs/vnode.c +++ b/servers/avfs/vnode.c @@ -177,9 +177,11 @@ PUBLIC int lock_vnode(struct vnode *vp, tll_access_t locktype) *===========================================================================*/ PUBLIC void unlock_vnode(struct vnode *vp) { +#if LOCK_DEBUG int i; register struct vnode *rvp; struct worker_thread *w; +#endif ASSERTVP(vp); #if LOCK_DEBUG diff --git a/servers/avfs/worker.c b/servers/avfs/worker.c index f8449109e..e5ae0c0e8 100644 --- a/servers/avfs/worker.c +++ b/servers/avfs/worker.c @@ -286,6 +286,16 @@ PUBLIC void worker_signal(struct worker_thread *worker) worker_wake(worker); } +/*===========================================================================* + * worker_stop * + *===========================================================================*/ +PUBLIC void worker_stop(struct worker_thread *worker) +{ + ASSERTW(worker); /* Make sure we have a valid thread */ + worker->w_job.j_m_in.m_type = -EIO; + worker_wake(worker); +} + /*===========================================================================* * worker_self * *===========================================================================*/