It seems that mdcache unexport can race with remove RPC.
Remove operation drops the sentinel ref and hence when the last call
to mdcache_put() happen during the execution of remove RPC, the
corresponding mdcache_entry will be freed. If an export remove comes
in while the remove OP is still executing, in mdcache_unexport() when
we call mdcache_lru_ref(entry, LRU_REQ_INITIAL) we can end up taking a
ref on the entry whose refcnt has already reached 0 and which is
currently going through mdcache_lru_clean() execution in the context
of remove. The entry is still present in the mdcache_fsal_export's
entry_list because mdcache_lru_clean() has not yet called the
mdc_clean_entry(). Now when do mdcache_put() for this entry later in
mdcache_unexport(), by this time the entry is already freed and we end
up executing mdcache_lru_clean() on a freed entry.
What we need to do inside mdcache_unexport() is to take QLOCK() and
check refcount, if it's 0, continue the for loop for next entry, if
it's not 0 than increment the ref count, drop the QLOCK and continue
with normal current execution path.
Does it makes sense?