Subject: Re: Redoing file system suspension API (update)
To: Jason Thorpe <thorpej@shagadelic.org>
From: Juergen Hannken-Illjes <hannken@eis.cs.tu-bs.de>
List: tech-kern
Date: 06/29/2006 21:52:43
On Thu, Jun 29, 2006 at 11:04:08AM -0700, Jason Thorpe wrote:
> 
> On Jun 29, 2006, at 9:54 AM, Juergen Hannken-Illjes wrote:
> 
> >At least as a base.  Lockmgr locks lack the "do I have a shared  
> >lock" query.
> >I need a lock where a thread already owning a shared lock succeeds  
> >when
> >it wants another shared lock.  Last time I looked lockmg locks had  
> >this only
> >for exclusive locks.
> 
> Um, I'm pretty sure that works already with lockmgr locks (e.g.  
> recursively acquiring a shared lock you already hold shared).  Just  
> make sure the acquire/releases are paired up and you should be fine.
> 
> Let's walk through the logic:
> 
>         case LK_SHARED:
>                 if (WEHOLDIT(lkp, pid, lid, cpu_num) == 0) {
> 
> We fall into this case because the lock is held shared (WEHOLDIT()  
> returns false).
> 
>                         /*
>                          * If just polling, check to see if we will  
> block.
>                          */
>                         if ((extflags & LK_NOWAIT) && (lkp->lk_flags &
>                             (LK_HAVE_EXCL | LK_WANT_EXCL |  
> LK_WANT_UPGRADE))) {
>                                 error = EBUSY;
>                                 break;
>                         }
>                         /*
>                          * Wait for exclusive locks and upgrades to  
> clear.
>                          */
>                         error = acquire(&lkp, &s, extflags, 0,
>                             LK_HAVE_EXCL | LK_WANT_EXCL |  
> LK_WANT_UPGRADE);
> 
> We wait until no exlusive holders are in / waiting.

And here we are.  I need shared lock recursion even if another thread wants
an exclusive lock.  The transaction lock will work like:

	xxx_read()
	{
		vn_trans_lock()  <-- (1)
		...
		xxx_getpages()
		...
		vn_trans_unlock()
	}

and

	xxx_getpages()
	{
		vn_trans_lock()  <-- (2)
		...
		vn_trans_unlock()
	}

When waiting at (2) the lock at (1) will never release.

>                         if (error)
>                                 break;
>                         lkp->lk_sharecount++;
> 
> ...and we increment the sharecount.
> 
>                         lkp->lk_flags |= LK_SHARE_NONZERO;
>                         COUNT(lkp, l, cpu_num, 1);
>                         break;
>                 }
> 
> 
> Looks to me like it should work just fine for what you want to do.
> 
> -- thorpej

-- 
Juergen Hannken-Illjes - hannken@eis.cs.tu-bs.de - TU Braunschweig (Germany)