VFS: improve crashed FS resource cleanup
When VFS detects that an FS has crashed and tries to clean up resources, it marks fairly late in the process that a vmnt is not to be used again (to send requests to). This allows a thread to become blocked on a vmnt after all blocked threads were stopped, but before it finds out it shouldn't try to send to that vmnt.
This commit is contained in:
parent
04eb5d326a
commit
1efb51b1de
3 changed files with 23 additions and 10 deletions
|
@ -273,8 +273,7 @@ char mount_label[LABEL_MAX] )
|
||||||
new_vmp->m_flags &= ~VMNT_MOUNTING;
|
new_vmp->m_flags &= ~VMNT_MOUNTING;
|
||||||
|
|
||||||
if (r != OK) {
|
if (r != OK) {
|
||||||
new_vmp->m_fs_e = NONE;
|
mark_vmnt_free(new_vmp);
|
||||||
new_vmp->m_dev = NO_DEV;
|
|
||||||
unlock_vnode(root_node);
|
unlock_vnode(root_node);
|
||||||
if (vp != NULL) {
|
if (vp != NULL) {
|
||||||
unlock_vnode(vp);
|
unlock_vnode(vp);
|
||||||
|
@ -349,11 +348,10 @@ char mount_label[LABEL_MAX] )
|
||||||
if (r != OK) {
|
if (r != OK) {
|
||||||
unlock_vnode(vp);
|
unlock_vnode(vp);
|
||||||
unlock_vnode(root_node);
|
unlock_vnode(root_node);
|
||||||
|
mark_vmnt_free(new_vmp);
|
||||||
unlock_vmnt(new_vmp);
|
unlock_vmnt(new_vmp);
|
||||||
put_vnode(vp);
|
put_vnode(vp);
|
||||||
put_vnode(root_node);
|
put_vnode(root_node);
|
||||||
new_vmp->m_dev = NO_DEV;
|
|
||||||
new_vmp->m_flags = 0;
|
|
||||||
unlock_bsf();
|
unlock_bsf();
|
||||||
return(r);
|
return(r);
|
||||||
}
|
}
|
||||||
|
@ -505,8 +503,7 @@ PUBLIC int unmount(
|
||||||
vmp->m_root_node->v_sdev = NO_DEV;
|
vmp->m_root_node->v_sdev = NO_DEV;
|
||||||
vmp->m_root_node = NULL;
|
vmp->m_root_node = NULL;
|
||||||
}
|
}
|
||||||
vmp->m_dev = NO_DEV;
|
mark_vmnt_free(vmp);
|
||||||
vmp->m_fs_e = NONE;
|
|
||||||
|
|
||||||
unlock_vmnt(vmp);
|
unlock_vmnt(vmp);
|
||||||
|
|
||||||
|
|
|
@ -331,6 +331,7 @@ _PROTOTYPE( int in_group, (struct fproc *rfp, gid_t grp) );
|
||||||
/* vmnt.c */
|
/* vmnt.c */
|
||||||
_PROTOTYPE( void check_vmnt_locks, (void) );
|
_PROTOTYPE( void check_vmnt_locks, (void) );
|
||||||
_PROTOTYPE( void check_vmnt_locks_by_me, (struct fproc *rfp) );
|
_PROTOTYPE( void check_vmnt_locks_by_me, (struct fproc *rfp) );
|
||||||
|
_PROTOTYPE( void mark_vmnt_free, (struct vmnt *vmp) );
|
||||||
_PROTOTYPE( struct vmnt *get_free_vmnt, (void) );
|
_PROTOTYPE( struct vmnt *get_free_vmnt, (void) );
|
||||||
_PROTOTYPE( struct vmnt *find_vmnt, (endpoint_t fs_e) );
|
_PROTOTYPE( struct vmnt *find_vmnt, (endpoint_t fs_e) );
|
||||||
_PROTOTYPE( struct vmnt *get_locked_vmnt, (struct fproc *rfp) );
|
_PROTOTYPE( struct vmnt *get_locked_vmnt, (struct fproc *rfp) );
|
||||||
|
|
|
@ -59,6 +59,17 @@ PUBLIC void check_vmnt_locks()
|
||||||
#endif
|
#endif
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*===========================================================================*
|
||||||
|
* mark_vmnt_free *
|
||||||
|
*===========================================================================*/
|
||||||
|
PUBLIC void mark_vmnt_free(struct vmnt *vmp)
|
||||||
|
{
|
||||||
|
ASSERTVMP(vmp);
|
||||||
|
|
||||||
|
vmp->m_fs_e = NONE;
|
||||||
|
vmp->m_dev = NO_DEV;
|
||||||
|
}
|
||||||
|
|
||||||
/*===========================================================================*
|
/*===========================================================================*
|
||||||
* clear_vmnt *
|
* clear_vmnt *
|
||||||
*===========================================================================*/
|
*===========================================================================*/
|
||||||
|
@ -83,10 +94,14 @@ PRIVATE void clear_vmnt(struct vmnt *vmp)
|
||||||
*===========================================================================*/
|
*===========================================================================*/
|
||||||
PUBLIC struct vmnt *get_free_vmnt(void)
|
PUBLIC struct vmnt *get_free_vmnt(void)
|
||||||
{
|
{
|
||||||
struct vmnt *vp;
|
struct vmnt *vmp;
|
||||||
|
|
||||||
for (vp = &vmnt[0]; vp < &vmnt[NR_MNTS]; ++vp)
|
for (vmp = &vmnt[0]; vmp < &vmnt[NR_MNTS]; ++vmp) {
|
||||||
if (vp->m_dev == NO_DEV) return(vp);
|
if (vmp->m_dev == NO_DEV) {
|
||||||
|
clear_vmnt(vmp);
|
||||||
|
return(vmp);
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
return(NULL);
|
return(NULL);
|
||||||
}
|
}
|
||||||
|
@ -167,6 +182,7 @@ PUBLIC void vmnt_unmap_by_endpt(endpoint_t proc_e)
|
||||||
struct vmnt *vmp;
|
struct vmnt *vmp;
|
||||||
|
|
||||||
if ((vmp = find_vmnt(proc_e)) != NULL) {
|
if ((vmp = find_vmnt(proc_e)) != NULL) {
|
||||||
|
mark_vmnt_free(vmp);
|
||||||
fs_cancel(vmp);
|
fs_cancel(vmp);
|
||||||
invalidate_filp_by_endpt(proc_e);
|
invalidate_filp_by_endpt(proc_e);
|
||||||
if (vmp->m_mounted_on) {
|
if (vmp->m_mounted_on) {
|
||||||
|
@ -174,7 +190,6 @@ PUBLIC void vmnt_unmap_by_endpt(endpoint_t proc_e)
|
||||||
* point. That is, the mount was succesful. */
|
* point. That is, the mount was succesful. */
|
||||||
put_vnode(vmp->m_mounted_on);
|
put_vnode(vmp->m_mounted_on);
|
||||||
}
|
}
|
||||||
clear_vmnt(vmp);
|
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
Loading…
Reference in a new issue