Re: sunrpc/cache.c: races while updating cache entries

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

 



On 13 Mar 2013 07:55:00 +0100 NeilBrown <neilb@xxxxxxx> wrote:

> On 11 Mar 2013 17:13:41 +0100 Bodo Stroesser <bstroesser@xxxxxxxxxxxxxx>
> wrote:
> 
> > Hi,
> > 
> > AFAICS, there is one more race in RPC cache.
> > 
> > The problem showed up for the "auth.unix.ip" cache, that
> > has a reader.
> > 
> > If a server thread tries to find a cache entry, it first
> > does a lookup (or calls ip_map_cached_get() in this specific
> > case). Then, it calls cache_check() for this entry.
> > 
> > If the reader updates the cache entry just between the
> > thread's lookup and cache_check() execution, cache_check()
> > will do an upcall for this cache entry. This is, because
> > sunrpc_cache_update() calls cache_fresh_locked(old, 0),
> > which sets expiry_time to 0.
> > 
> > Unfortunately, the reply to the upcall will not dequeue
> > the queued cache_request, as the reply will be assigned to
> > the cache entry newly created by the above cache update.
> > 
> > The result is a growing queue of orphaned cache_request
> > structures --> memory leak.
> > 
> > I found this on a SLES11 SP1 with a backport of the latest
> > patches that fix the other RPC races. On this old kernel,
> > the problem also leads to svc_drop() being called for the
> > affected RPC request (after svc_defer()).
> > 
> > Best Regards
> > Bodo
> 
> I don't think this is a real problem.
> The periodic call to "cache_clean" should find these orphaned requests and
> purge them.  So you could get a short term memory leak, but it should
> correct itself.
> Do you agree?
> 
> Thanks,
> NeilBrown

Meanwhile I found the missing part of the race!

It's just what I wrote above but additionally, immediately after
the reader updated the cache, cache_clean() unhashes the old cache
entry. In that case:
1) the thread will queue a request for a cache entry, that isn't
   in the hash lists.
2) cache_clean() never will access this old cache entry again
3) every further cache update will call cache_dequeue() for a newer
   cache entry, the request is never dequeued

--> memory leak.

I verified this inserting some debug instructions. In a testrun
that triggered 6 times, and the queue printed by crash after the
run had 6 orphaned entries.

As I wrote yesterday, I have a patch that solves the problem by
retesting the state of the cache entry after setting CACHE_PENDING
in cache_check(). I can send it if you like.

Bodo

P.S.:
Maybe I'm wrong, but AFAICS, there are two further minor problems
regarding (nearly) expired cache entries:
a) ip_map_cached_get() in some situations can return an already
   outdated (it uses cache_valid that not fully checks the state)
   cache entry. If cache_check() is caclled for that entry, it will
   fail, I think
b) Generally, if a cache entry is returned by sunrpc_cache_lookup()
   and the entry is in the last second of it's expiry_time, the 
   clock might move to the next second before cache_check is called.
   If this happens, cache_check will fail, I think.
Do you agree?
ÿôèº{.nÇ+?·?®?­?+%?Ëÿ±éݶ¥?wÿº{.nÇ+?·¥?{±þwìþ)í?æèw*jg¬±¨¶????Ý¢jÿ¾«þG«?éÿ¢¸¢·¦j:+v?¨?wèjØm¶?ÿþø¯ù®w¥þ?àþf£¢·h??â?úÿ?Ù¥



[Index of Archives]     [Linux Filesystem Development]     [Linux USB Development]     [Linux Media Development]     [Video for Linux]     [Linux NILFS]     [Linux Audio Users]     [Yosemite Info]     [Linux SCSI]

  Powered by Linux