From 1efb51b1de174cdecf507d8731e462e9269da4c5 Mon Sep 17 00:00:00 2001 From: Thomas Veerman Date: Wed, 22 Feb 2012 13:54:35 +0000 Subject: [PATCH] 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. --- servers/vfs/mount.c | 9 +++------ servers/vfs/proto.h | 1 + servers/vfs/vmnt.c | 23 +++++++++++++++++++---- 3 files changed, 23 insertions(+), 10 deletions(-) diff --git a/servers/vfs/mount.c b/servers/vfs/mount.c index 4e4666d5a..a89c1c214 100644 --- a/servers/vfs/mount.c +++ b/servers/vfs/mount.c @@ -273,8 +273,7 @@ char mount_label[LABEL_MAX] ) new_vmp->m_flags &= ~VMNT_MOUNTING; if (r != OK) { - new_vmp->m_fs_e = NONE; - new_vmp->m_dev = NO_DEV; + mark_vmnt_free(new_vmp); unlock_vnode(root_node); if (vp != NULL) { unlock_vnode(vp); @@ -349,11 +348,10 @@ char mount_label[LABEL_MAX] ) if (r != OK) { unlock_vnode(vp); unlock_vnode(root_node); + mark_vmnt_free(new_vmp); unlock_vmnt(new_vmp); put_vnode(vp); put_vnode(root_node); - new_vmp->m_dev = NO_DEV; - new_vmp->m_flags = 0; unlock_bsf(); return(r); } @@ -505,8 +503,7 @@ PUBLIC int unmount( vmp->m_root_node->v_sdev = NO_DEV; vmp->m_root_node = NULL; } - vmp->m_dev = NO_DEV; - vmp->m_fs_e = NONE; + mark_vmnt_free(vmp); unlock_vmnt(vmp); diff --git a/servers/vfs/proto.h b/servers/vfs/proto.h index 432ef3a52..ddb4859c9 100644 --- a/servers/vfs/proto.h +++ b/servers/vfs/proto.h @@ -331,6 +331,7 @@ _PROTOTYPE( int in_group, (struct fproc *rfp, gid_t grp) ); /* vmnt.c */ _PROTOTYPE( void check_vmnt_locks, (void) ); _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 *find_vmnt, (endpoint_t fs_e) ); _PROTOTYPE( struct vmnt *get_locked_vmnt, (struct fproc *rfp) ); diff --git a/servers/vfs/vmnt.c b/servers/vfs/vmnt.c index bb3dc0746..6e4c9ed0d 100644 --- a/servers/vfs/vmnt.c +++ b/servers/vfs/vmnt.c @@ -59,6 +59,17 @@ PUBLIC void check_vmnt_locks() #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 * *===========================================================================*/ @@ -83,10 +94,14 @@ PRIVATE void clear_vmnt(struct vmnt *vmp) *===========================================================================*/ PUBLIC struct vmnt *get_free_vmnt(void) { - struct vmnt *vp; + struct vmnt *vmp; - for (vp = &vmnt[0]; vp < &vmnt[NR_MNTS]; ++vp) - if (vp->m_dev == NO_DEV) return(vp); + for (vmp = &vmnt[0]; vmp < &vmnt[NR_MNTS]; ++vmp) { + if (vmp->m_dev == NO_DEV) { + clear_vmnt(vmp); + return(vmp); + } + } return(NULL); } @@ -167,6 +182,7 @@ PUBLIC void vmnt_unmap_by_endpt(endpoint_t proc_e) struct vmnt *vmp; if ((vmp = find_vmnt(proc_e)) != NULL) { + mark_vmnt_free(vmp); fs_cancel(vmp); invalidate_filp_by_endpt(proc_e); 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. */ put_vnode(vmp->m_mounted_on); } - clear_vmnt(vmp); } }