tech-net archive

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index][Old Index]

Re: RFC: gif(4) MP-ify



Hi,

Thank you for your closeup review!

On 2016/01/11 14:48, Taylor R Campbell wrote:
>    Date: Wed, 6 Jan 2016 14:19:01 +0900
>    From: Kengo NAKAHARA <k-nakahara%iij.ad.jp@localhost>
> 
>    On 2016/01/06 3:40, Taylor R Campbell wrote:
>    > There are a couple other things I'm concerned about in the patch -- I
>    > notice you're doing softint_establish with a lock held.  Maybe that's
>    > OK, but it makes me a little nervous.  I don't have time right now but
>    > I would like to take a closer look in the next few days at some of the
>    > changes like that that your patch makes.
> 
>    It works for my environment for now..., meanwhile I see your point.
>    Thank you for your help. I'm looking forward to your review.
> 
> I took a closer look at your patch, and at your fix for 50522.  I'm
> concerned about a few things:
> 
> - missing memory barriers in handling the reference counts,
> - (future) performance impact of atomics in gifintr and gif_output,
> and
> - global invariants for the gif list, and overcomplexity of the
> locking scheme.
> 
> In particular:
> 
> - The following fragment of gifintr probably needs a memory barrier on
> non-x86 platforms:
> 
> 	atomic_inc_uint(&sc->gif_si_refs);
> 	if (sc->gif_pdst == NULL || sc->gif_psrc == NULL) {
> 		...
> 	}

The codes about gif_si_refs are removed by if_gif.c:r1.103 cvs commit,
so there is no atomic operation in gif(4) codes.
However, the locking notes still has gif_si_lock, sorry.

BTW, I heard a memory barrier is not required after rwlock or mutex.
Doesn't it true for non-x86 platforms?


> Otherwise, gifintr on CPU 0 might load nonnull values from
> sc->gif_pdst and sc->gif_psrc before gif_set_tunnel on CPU 1 sees
> positive sc->gif_si_refs.  I'm a little unclear on the rest of the
> protocol -- but I suspect it can be done without atomics or mutexes
> anyway in the packet-processing path.
> 
> - Atomics are expensive interprocessor synchronization operations, so
> we should avoid them where unnecessary for MP-scalability --
> particularly in the packet-processing path.  In this case I think it
> shouldn't be too hard to avoid: we simply need to prevent calls to
> gif_output before we do softint_disestablish.

Yes, I removed atomic operations from gif(4) packet-processing path,
as note above. I think the fix for PR/50522 fixes the race between
gif_output and softint_disestablish.


> - With your proposed patch, if CPU 0 and CPU 1 both run gif_set_tunnel
> with the same address, then they might
> 
> (a) first find no existing gif(4) having that address;
> (b) next configure gif0 and gif1 with the same address; and then
> (c) finally leave the system in a state where gif0 and gif1 have the
> same address,
> 
> which violates the global invariant that gif_set_tunnel tries to
> enforce.  So we really need (a), (b), and (c) to happen atomically.

I see. Sorry, I missed the pattern...


> I think the following protocol should be simpler and safer:
> 
> - One global interruptible lock for the system's gif(4) configuration.
> - No per-gif(4) locks at all.
> - Split gif_encap_detach (and in/in6_gif_detach) into two parts:
>   . gif_encap_pause: prevent further use of gif_output (encap_detach)
>   . gif_encap_detach: destroy data structures associated with it (rtcache_free)
> - Make gif_set_tunnel do:
>   1. acquire global lock
>   2. check invariant -- reject duplicate gif src/dst addresses
>   3. gif_encap_pause
>   4. softint_disestablish
>   5. gif_encap_detach, sockaddr_free
>   6. gif_encap_attach
>   7. softint_establish
>   8. release global lock
> - Make gif_delete_tunnel do:
>   1. acquire global lock
>   2. gif_encap_pause
>   3. softint_disestablish
>   4. gif_encap_detach, sockaddr_free
>   5. release global lock

Hmm... ip_encap.c(encap_attach and encap_detach) is used by
not only gif(4) but also stf(4) for now, so I think the global
interruptible lock might be the common lock among gif(4), stf(4)
and other interfaces which will use ip_encap.c.

Except it, the processing seems excellent.


> The global lock, for the moment, can just be KERNEL_LOCK: it is
> acquired only during ifconfig(8), not in the packet-processing path.
> Or you could make an interruptible lock out of a mutex, condvar, and
> flag.  It should be interruptible so that if `ifconfig gif0 tunnel
> ...' hangs for any reason, then another process trying to do the same
> can handle ^C.
> 
> 
> Here's a quick sketch of an interruptible lock:

I feel like avoiding KERNEL_LOCK... I will implement based on the sketch.

Thank you very much for your many great advices!


Thanks,

-- 
//////////////////////////////////////////////////////////////////////
Internet Initiative Japan Inc.

Device Engineering Section,
Core Product Development Department,
Product Division,
Technology Unit

Kengo NAKAHARA <k-nakahara%iij.ad.jp@localhost>


Home | Main Index | Thread Index | Old Index