vfs_glusterfs: fix directory fd leak via FSP extension destructor
When Samba closes a directory backed by vfs_glusterfs, the glfs_fd_t
opened by vfs_gluster_openat() is never closed. This leaks one
libgfapi file descriptor and one server-side fd_t in glusterfsd per
directory open/close cycle. With persistent SMB2 connections the
leak is unbounded and drives monotonic RSS growth on the GlusterFS
brick process.
The leak happens because vfs_glusterfs creates two independent
glfs_fd_t handles per directory: one via glfs_open() in
vfs_gluster_openat(), stored in the FSP extension, and another via
glfs_opendir() in vfs_gluster_fdopendir(), tracked by struct smb_Dir.
On close, smb_Dir_destructor() closes the opendir handle and sets the
pathref fd to -1. fd_close() then returns early without calling
SMB_VFS_CLOSE, so vfs_gluster_close() never runs and the glfs_open()
handle is orphaned. The original code passed NULL as the destroy
callback to VFS_ADD_FSP_EXTENSION, so there was no safety net.
The default VFS does not have this problem because fdopendir(3) wraps
the existing kernel fd rather than opening a new handle. libgfapi
has no equivalent -- glfs_opendir() always creates an independent
handle by path. The actual glfs_fd_t is stored in the FSP extension,
not in fsp->fh->fd (which holds a sentinel value), so Samba's generic
close path cannot reach it.
Register vfs_gluster_fsp_ext_destroy() as the FSP extension destroy
callback. It calls glfs_close() on the stored pointer and is invoked
by vfs_remove_all_fsp_extensions() during file_free(), which runs
unconditionally for every fsp. In the explicit close path,
vfs_gluster_close() NULLs the extension pointer before calling
VFS_REMOVE_FSP_EXTENSION to prevent double-close. This follows the
same pattern used by vfs_ceph_new.c (vfs_ceph_fsp_ext_destroy_cb).
Observed on a production file server with persistent SMB2 connections
and continuous directory operations. GlusterFS brick statedumps
showed fd_t pool growth from 1,993 to 80,350 active instances over
6 days, roughly 13,000 leaked fds per day per brick.
RN: Fix a directory file descriptor leak in vfs_glusterfs that caused
unbounded memory growth on the GlusterFS brick with persistent SMB2
connections.