diff --git a/sys/vm/vm_fault.c b/sys/vm/vm_fault.c index 47a1bd57ef24..11993054d0c0 100644 --- a/sys/vm/vm_fault.c +++ b/sys/vm/vm_fault.c @@ -563,6 +563,14 @@ RetryFault:; } readrest: + /* + * At this point, we have either allocated a new page or found + * an existing page that is only partially valid. + * + * We hold a reference on the current object and the page is + * exclusive busied. + */ + /* * If the pager for the current object might have the page, * then determine the number of additional pages to read and @@ -632,18 +640,23 @@ RetryFault:; */ if (fs.object->type != OBJT_DEFAULT) { /* - * We have either allocated a new page or found an - * existing page that is only partially valid. We - * hold a reference on fs.object and the page is - * exclusive busied. + * Release the map lock before locking the vnode or + * sleeping in the pager. (If the current object has + * a shadow, then an earlier iteration of this loop + * may have already unlocked the map.) */ unlock_map(&fs); if (fs.object->type == OBJT_VNODE && (vp = fs.object->handle) != fs.vp) { + /* + * Perform an unlock in case the desired vnode + * changed while the map was unlocked during a + * retry. + */ unlock_vp(&fs); - locked = VOP_ISLOCKED(vp); + locked = VOP_ISLOCKED(vp); if (locked != LK_EXCLUSIVE) locked = LK_SHARED;