deeraj.patil@ibm.com has uploaded this change for review. ( https://review.gerrithub.io/c/ffilz/nfs-ganesha/+/1232496?usp=email ) Change subject: [mdcache] : Export cleanup, releasing FD's. ...................................................................... [mdcache] : Export cleanup, releasing FD's. When an export is removed (SIGHUP or admin), the call sequence is: prepare_unexport -> state_release_export -> unexport -> exp_release. NFSv3 is stateless: state_release_export closes nothing for NFSv3. Global FDs on mdcache entries (opened by NFSv3 READ/WRITE) survive with fsal_export pointers that are about to be freed. The LRU reaper running concurrently can dereference those pointers after exp_release frees the export struct (use-after-free). In-flight NFSv3 threads that already resolved a file handle can also call reopen_fsal_fd between unexport's fsal_close calls and exp_release, re-inserting a FD into the global LRU for a being-freed export. Nested export case (exportA inside exportB): entries shared between exportA and exportB both needs to drain global FD base on which export is getting released. And is tracked via cleanup_export/cleanup_pending; the export drain waits for all of them before releasing the export struct. Two early-stop flags prevent new FDs from being created on a dying export: EXPORT_STALE is set in release_export before prepare_unexport, and MDC_UNEXPORT is set in mdcache_prepare_unexport itself. During mdcache_unexport, global FDs are force-closed via fsal_close on every entry; entries that become fully unmapped (expmap==NULL) are additionally tracked by setting entry->cleanup_export and incrementing exp->cleanup_pending, while entries still mapped to a sibling export only get their FD closed (no tracking needed, they stay alive). The same tracking applies in mdcache_unmount for junction entries. When the LRU thread finally cleans a tracked entry in mdcache_lru_clean, it decrements cleanup_pending and signals cleanup_cond when it hits zero; if mdcache_lru_cleanup_try_push fails due to active refs, the tracking fields are left in place so the wait still covers that entry. Finally, mdcache_exp_release calls mdcache_drain_export_cleanup() a simple cond var wait on cleanup_pending == 0 before freeing anything, guaranteeing no LRU thread or reaper can dereference the export after it is freed. Change-Id: I44f761479883e84e43f8a23f5c3a9fbe563490fd Signed-off-by: Deeraj.Patil <Deeraj.Patil@ibm.com> --- M src/FSAL/Stackable_FSALs/FSAL_MDCACHE/mdcache_export.c M src/FSAL/Stackable_FSALs/FSAL_MDCACHE/mdcache_int.h M src/FSAL/Stackable_FSALs/FSAL_MDCACHE/mdcache_lru.c M src/FSAL/Stackable_FSALs/FSAL_MDCACHE/mdcache_main.c M src/support/exports.c 5 files changed, 121 insertions(+), 1 deletion(-) git pull ssh://review.gerrithub.io:29418/ffilz/nfs-ganesha refs/changes/96/1232496/1 -- To view, visit https://review.gerrithub.io/c/ffilz/nfs-ganesha/+/1232496?usp=email To unsubscribe, or for help writing mail filters, visit https://review.gerrithub.io/settings?usp=email Gerrit-MessageType: newchange Gerrit-Project: ffilz/nfs-ganesha Gerrit-Branch: next Gerrit-Change-Id: I44f761479883e84e43f8a23f5c3a9fbe563490fd Gerrit-Change-Number: 1232496 Gerrit-PatchSet: 1 Gerrit-Owner: deeraj.patil@ibm.com