[PATCH 08/20] 3409e4f1e8f2 NFSD: Make it possible to use svc_set_num_threads_syncNFSD: 使能使用 svc_set_num_threads_sync
当前 nfsd 无法使用 svc_set_num_threads_sync。它使用的是不会等待线程退出的 svc_set_num_threads,并通过一个单独机制(nfsd_shutdown_complete)来等待完成。
nfsd 与其他服务不同的原因在于 nfsd 线程可以在调用 svc_set_num_threads 后单独退出——它们在接收到 SIGKILL 时终止。此外,当最后一个线程退出时,服务必须关闭(套接字关闭)。
为此,需要获取 nfsd_mutex,并且由于在调用 svc_set_num_threads 时需要持有该互斥锁,这二者无法相互等待。
本补丁修改了 nfsd 线程,使其能够在不阻塞 nfsd_mutex 的情况下释放对服务的引用,以便可以使用 svc_set_num_threads_sync:
- 如果它可以释放非最后一个引用,则直接释放。这不会触发关闭,也不需要互斥锁。这会发生在除最后一个被发信号的线程以及由 nfsd_shutdown_threads() 关闭的线程之外的所有线程上。
- 如果它可以在不阻塞的情况下获取互斥锁(trylock),则获取后释放引用。这很可能发生在最后一个被 SIGKILL 杀死的线程上。
- 否则,可能有其他不相关任务持有该互斥锁(可能在另一个网络命名空间中),或者 nfsd_shutdown_threads() 正准备获取对服务的引用,此时我们可以安全地释放我们的引用。我们无法方便地获取这些事件的唤醒通知,而且也不太可能需要,因此我们会短暂休眠,然后再次检查。
通过此方式,我们可以废弃 nfsd_shutdown_complete 和 nfsd_complete_shutdown(),并切换到 svc_set_num_threads_sync。
相关邮件:
我能找到的此崩溃的唯一可能原因是,在调用 nfsd_shutdown_net() 和随后调用 nfsd_shutdown_generic() 时,nfsd 线程仍在运行,从而导致工作队列被销毁。
这些线程都会收到 SIGKILL 信号,但没有任何机制去等待它们执行完毕。
这一点在提交
Commit: 3409e4f1e8f2 ("NFSD: Make it possible to use svc_set_num_threads_sync")
中得到了修正:在同步模式下,线程会被同步地停止,因此可以确保在移除工作队列之前,所有线程都已经停止运行。前置补丁:
c6c7f2a84da4 nfsd: Ensure knfsd shuts down when the "nfsd" pseudofs is unmounted:
/proc/fs/nfsd卸载时确保所有nfsd线程全部停止
[PATCH 07/10] 97ad4031e295 nfsd4: add a client info file](https://lore.kernel.org/all/1556201060-7947-8-git-send-email-bfields@redhat.com/)[PATCH 01/20] 89b24336f03a NFSD: handle error better in write_ports_addfd():
确保nfsd_serv刚创建时才销毁[PATCH 02/20] df5e49c880ea SUNRPC: change svc_get() to return the svc.:
让svc_get()有返回值[PATCH 03/20] 8c62d12740a1 SUNRPC/NFSD: clean up get/put functions.:
重构svc_destroy()和nfsd_destroy()
[PATCH v2] c20106944eb6 NFSD: Keep existing listeners on portlist error:
如果已经存在sockets就只是减少计数,不调用nfsd_destroy()[PATCH 04/20] ec52361df99b SUNRPC: stop using ->sv_nrthreads as a refcount:
sv_nrthreads只作为线程计数,新增sv_refcnt作为引用计数
[PATCH 1/5] 2a501f55cd64 nfsd: call nfsd_last_thread() before final nfsd_put():
失败时调用nfsd_last_thread()
[PATCH 05/12] 9f28a971ee9f nfsd: separate nfsd_last_thread() from nfsd_put():
从nfsd_put()中分离出函数nfsd_last_thread()
[PATCH v2 3/8] 87cdd8641c8a SUNRPC: Remove svo_shutdown method:
删除结构体的.svo_shutdown(),在使用的地方直接调用函数[PATCH v2 4/8] 352ad31448fe SUNRPC: Rename svc_create_xprt():
函数重命名成svc_xprt_create()[PATCH v2 6/8] c7d7ec8f043e SUNRPC: Remove svc_shutdown_net():
svc_shutdown_net()换成svc_xprt_destroy_all()nfsd.h), 4.19可不合:
73598a0cfb21 nfsd: don't allocate the versions array.[PATCH] 88956eabfdea NFSD: fix possible oops when nfsd/pool_stats is closed.:
修复可能的空指针解引用[PATCH] 64e6304169f1 nfsd: drop the nfsd_put helper[PATCH 05/20] 9b6c8c9bebcc nfsd: make nfsd_stats.th_cnt atomic_t:
把nfsd_stats.th_cnt变成原子变量
[PATCH 06/20] 2a36395fac3b SUNRPC: use sv_lock to protect updates to sv_nrthreads.:
对sv_nrthreads加锁[PATCH 07/20] 9d3792aefdcd NFSD: narrow nfsd_mutex protection in nfsd thread:
缩小nfsd_mutex加锁的范围[PATCH 09/20] 3ebdbe5203a8 SUNRPC: discard svo_setup and rename svc_set_num_threads_sync():
函数改名为svc_set_num_threads()[PATCH 10/20] d057cfec4940 NFSD: simplify locking for network notifier.:
使用自旋锁nfsd_notifier_lock
nfsd_reset_versions()),4.19可不合:
e333f3bbefe3 nfsd: Allow containers to set supported nfs versions