On Wed, Mar 05, 2014 at 02:21:04PM -0500, John Baldwin wrote:
> On Wednesday, March 05, 2014 6:07:23 am Konstantin Belousov wrote:
> > On Wed, Mar 05, 2014 at 11:41:24AM +0200, Andriy Gapon wrote:
> > > on 04/03/2014 18:45 John Baldwin said the following:
> > > > So I'm not sure how to fix this.  The crash is in this code in 
> > > > vm_object_deallocate():
> > > > 
> > > >                         if (object->type == OBJT_SWAP &&
> > > >                             (object->flags & OBJ_TMPFS) != 0) {
> > > >                                 vp = object->un_pager.swp.swp_tmpfs;
> > > >                                 vhold(vp);
> > > >                                 VM_OBJECT_WUNLOCK(object);
> > > >                                 vn_lock(vp, LK_EXCLUSIVE | LK_RETRY);
> > > >                                 vdrop(vp);
> > > >                                 VM_OBJECT_WLOCK(object);
> > > >                                 if (object->type == OBJT_DEAD ||
> > > >                                     object->ref_count != 1) {
> > > >                                         VM_OBJECT_WUNLOCK(object);
> > > >                                         VOP_UNLOCK(vp, 0);
> > > >                                         return;
> > > >                                 }
> > > >                                 if ((object->flags & OBJ_TMPFS) != 0)
> > > >                                         VOP_UNSET_TEXT(vp);
> > > >                                 VOP_UNLOCK(vp, 0);
> > > >                         }
> > > > 
> > > > The vdrop() is dropping the count to zero and trying to free the vnode. 
> > > >  The 
> > > > real problem I think is that swp_tmpfs doesn't have an implicit vhold() 
> > > > on the 
> > > > vnode, so in this case, the code is doing a vhold/vn_lock/vdrop of an 
> > > > already-
> > > > free vnode.  For OBJT_VNODE objects, the reference from the object back 
> > > > to the 
> > > > vnode holds a vref() that gets released by a vput() in 
> > > > vm_object_vndeallocate().
> > > > 
> > > > One fix might be to chagne smp_tmpfs to hold a vhold reference.  This 
> > > > is 
> > > > untested but might work (but I'm also not sure that this is the right 
> > > > thing in 
> > > > that I don't know what other effects it might have).
> > > 
> > > I agree with your analysis, but I don't think that a filesystem holding 
> > > its own
> > > vnode is a good idea.  If I am not mistaken, that would prevent tmpfs 
> > > vnodes
> > > from going to free list.
> > > I'd rather try to modify vm_object_deallocate() code.  E.g. vdrop() could 
> > > be
> > > called after VOP_UNLOCK().  Alternatively, the code could handle a doomed 
> > > vnode
> > > in a different way.
> > 
> > I agree with Andrey, it is just a bug to vdrop() before unlock.
> > Please try this.
> 
> Ok, my only worry is in the case of Bryan's panic, the hold count on the vnode
> was already zero before vhold() was called, so is it possible that it is a 
> stale
> pointer or is there some other implicit reference that prevents that?  If it 
> can't
> be stale, I think deferring the vdrop() is fine.

The object->un_pager.swp.swp_tmpfs is cleared under the object lock
before the vnode is reclaimed, i.e. long before the vnode can be freed.
swp_tmpfs should be kept in sync with the OBJ_TMPFS flag, so the
vhold() is safe while flag is set and object is locked.

Attachment: pgpP559xHxzMH.pgp
Description: PGP signature

Reply via email to