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:
parent
b956493367
commit
91a38b6d4e
3 changed files with 34 additions and 29 deletions
|
@ -87,9 +87,10 @@ int flags; /* device flags */
|
|||
* NONE, we're supposed to unmap it.
|
||||
*/
|
||||
|
||||
int slot;
|
||||
int slot, s;
|
||||
size_t len;
|
||||
struct dmap *dp;
|
||||
struct fproc *rfp;
|
||||
|
||||
/* Get pointer to device entry in the dmap table. */
|
||||
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 */
|
||||
if (! (flags & DRV_FORCED)) {
|
||||
struct fproc *rfp;
|
||||
|
||||
if (isokendpt(proc_nr_e, &slot) != OK)
|
||||
s = isokendpt(proc_nr_e, &slot);
|
||||
if (s != OK) {
|
||||
/* This is not a problem only when we force this driver mapping */
|
||||
if (! (flags & DRV_FORCED))
|
||||
return(EINVAL);
|
||||
|
||||
} else {
|
||||
rfp = &fproc[slot];
|
||||
rfp->fp_flags |= FP_SYS_PROC; /* Process is a driver */
|
||||
}
|
||||
|
|
|
@ -147,33 +147,38 @@ static void handle_work(void *(*func)(void *arg))
|
|||
|
||||
proc_e = m_in.m_source;
|
||||
|
||||
if ((vmp = find_vmnt(proc_e)) != NULL) {
|
||||
/* 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 (fp->fp_flags & FP_SYS_PROC) {
|
||||
if (worker_available() == 0) {
|
||||
/* No worker threads available to handle call */
|
||||
if (deadlock_resolving) {
|
||||
/* Already trying to resolve a deadlock, can't
|
||||
* handle more, sorry */
|
||||
vmp->m_flags &= ~VMNT_CALLBACK;
|
||||
if (!deadlock_resolving) {
|
||||
if ((vmp = find_vmnt(proc_e)) != NULL) {
|
||||
/* A call back or dev result from an FS
|
||||
* endpoint. Set call back flag. Can do only
|
||||
* one call back at a time.
|
||||
*/
|
||||
if (vmp->m_flags & VMNT_CALLBACK) {
|
||||
reply(proc_e, EAGAIN);
|
||||
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;
|
||||
dl_worker_start(func);
|
||||
return;
|
||||
}
|
||||
/* Already trying to resolve a deadlock, can't
|
||||
* handle more, sorry */
|
||||
|
||||
reply(proc_e, EAGAIN);
|
||||
return;
|
||||
}
|
||||
}
|
||||
|
||||
worker_start(func);
|
||||
|
|
|
@ -62,7 +62,6 @@ struct dmap *get_dmap(endpoint_t proc_e);
|
|||
int do_mapdriver(void);
|
||||
int map_service(struct rprocpub *rpub);
|
||||
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
|
||||
dev_style, int flags);
|
||||
int map_service(struct rprocpub *rpub);
|
||||
|
|
Loading…
Reference in a new issue