deeraj.patil(a)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(a)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(a)ibm.com