VFS: fix dead lock

When running out of worker threads to handle device replies a dead
lock resolver thread is used. However, it was only used for FS
endpoints; it is now used for "system processes" (drivers and FS
endpoints). Also, drivers were marked as system process when they
were not "forced" to map (i.e., mapping was done before endpoint was
alive).
This commit is contained in:
Thomas Veerman 2012-04-02 15:20:05 +00:00
parent b956493367
commit 91a38b6d4e
3 changed files with 34 additions and 29 deletions

View file

@ -87,9 +87,10 @@ int flags; /* device flags */
* NONE, we're supposed to unmap it. * NONE, we're supposed to unmap it.
*/ */
int slot; int slot, s;
size_t len; size_t len;
struct dmap *dp; struct dmap *dp;
struct fproc *rfp;
/* Get pointer to device entry in the dmap table. */ /* Get pointer to device entry in the dmap table. */
if (major < 0 || major >= NR_DEVICES) return(ENODEV); if (major < 0 || major >= NR_DEVICES) return(ENODEV);
@ -105,12 +106,12 @@ int flags; /* device flags */
} }
/* Check process number of new driver if it was alive before mapping */ /* Check process number of new driver if it was alive before mapping */
if (! (flags & DRV_FORCED)) { s = isokendpt(proc_nr_e, &slot);
struct fproc *rfp; if (s != OK) {
/* This is not a problem only when we force this driver mapping */
if (isokendpt(proc_nr_e, &slot) != OK) if (! (flags & DRV_FORCED))
return(EINVAL); return(EINVAL);
} else {
rfp = &fproc[slot]; rfp = &fproc[slot];
rfp->fp_flags |= FP_SYS_PROC; /* Process is a driver */ rfp->fp_flags |= FP_SYS_PROC; /* Process is a driver */
} }

View file

@ -147,33 +147,38 @@ static void handle_work(void *(*func)(void *arg))
proc_e = m_in.m_source; proc_e = m_in.m_source;
if ((vmp = find_vmnt(proc_e)) != NULL) { if (fp->fp_flags & FP_SYS_PROC) {
/* A call back or dev result from an FS endpoint */
/* Set call back flag. We assume that an FS does only one call back
* at a time */
vmp->m_flags |= VMNT_CALLBACK;
/* When an FS point has to make a call back in order to mount, force
* its device to a "none device" so block reads/writes will be handled
* by ROOT_FS_E.
*/
if (vmp->m_flags & VMNT_MOUNTING)
vmp->m_flags |= VMNT_FORCEROOTBSF;
if (worker_available() == 0) { if (worker_available() == 0) {
/* No worker threads available to handle call */ if (!deadlock_resolving) {
if (deadlock_resolving) { if ((vmp = find_vmnt(proc_e)) != NULL) {
/* Already trying to resolve a deadlock, can't /* A call back or dev result from an FS
* handle more, sorry */ * endpoint. Set call back flag. Can do only
vmp->m_flags &= ~VMNT_CALLBACK; * one call back at a time.
*/
if (vmp->m_flags & VMNT_CALLBACK) {
reply(proc_e, EAGAIN); reply(proc_e, EAGAIN);
return; return;
} }
vmp->m_flags |= VMNT_CALLBACK;
/* When an FS endpoint has to make a call back
* in order to mount, force its device to a
* "none device" so block reads/writes will be
* handled by ROOT_FS_E.
*/
if (vmp->m_flags & VMNT_MOUNTING)
vmp->m_flags |= VMNT_FORCEROOTBSF;
}
deadlock_resolving = 1; deadlock_resolving = 1;
dl_worker_start(func); dl_worker_start(func);
return; return;
} }
/* Already trying to resolve a deadlock, can't
* handle more, sorry */
reply(proc_e, EAGAIN);
return;
}
} }
worker_start(func); worker_start(func);

View file

@ -62,7 +62,6 @@ struct dmap *get_dmap(endpoint_t proc_e);
int do_mapdriver(void); int do_mapdriver(void);
int map_service(struct rprocpub *rpub); int map_service(struct rprocpub *rpub);
void dmap_unmap_by_endpt(int proc_nr); void dmap_unmap_by_endpt(int proc_nr);
struct dmap *get_dmap(endpoint_t proc_e);
int map_driver(const char *label, int major, endpoint_t proc_nr, int int map_driver(const char *label, int major, endpoint_t proc_nr, int
dev_style, int flags); dev_style, int flags);
int map_service(struct rprocpub *rpub); int map_service(struct rprocpub *rpub);