From f0786a7497146944d39670a6c124e3392d84ea8a Mon Sep 17 00:00:00 2001 From: Kefu Chai Date: Fri, 30 Jan 2026 16:43:03 +0800 Subject: [PATCH] pybind/cephfs: replace deprecated IF with C preprocessor macro Complete the migration started in 719b74984605 by replacing deprecated Cython IF statements with C preprocessor conditionals. The cephfs binding used deprecated IF/ELSE statements in types.pxd for platform-specific dirent struct definitions. The challenge was that dirent has a d_off field on Linux but not on FreeBSD/Darwin. Solution: - Remove dirent declaration from types.pxd (had deprecated IF) - Declare dirent with common fields in c_cephfs.pxd - Define DIRENT_D_OFF(d) C macro using C preprocessor conditionals: - Returns d->d_off on Linux - Returns 0UL on FreeBSD/Darwin - Use DIRENT_D_OFF macro in cephfs.pyx instead of conditional field access - No Tempita preprocessing or UNAME_SYSNAME needed - Revert setup.py to original (no changes needed) Why C preprocessor instead of Tempita: Tempita requires preprocessing files with setup.py, which works for .pyx files but is problematic for .pxd files since setup.py runs in the source directory and could overwrite sources. The C preprocessor approach is cleaner, requires no setup.py changes, and follows the pattern used in rados.pxd for BUILD_DOC conditionals. This eliminates all deprecated Cython IF statements and prepares for Cython 3.0+ compatibility. The C preprocessor approach allows portable access to platform-specific struct fields without Cython IF. Signed-off-by: Kefu Chai --- src/pybind/cephfs/c_cephfs.pxd | 21 ++++++++++++++++ src/pybind/cephfs/cephfs.pyx | 42 +++++++++++-------------------- src/pybind/cephfs/mock_cephfs.pxi | 25 +++++++++++++++++- src/pybind/cephfs/types.pxd | 15 ----------- 4 files changed, 59 insertions(+), 44 deletions(-) diff --git a/src/pybind/cephfs/c_cephfs.pxd b/src/pybind/cephfs/c_cephfs.pxd index 8245f12f69f..88fd6abb4f8 100644 --- a/src/pybind/cephfs/c_cephfs.pxd +++ b/src/pybind/cephfs/c_cephfs.pxd @@ -4,6 +4,27 @@ from libc.stdint cimport * from types cimport * +# dirent struct with common fields and platform-specific d_off handling +cdef extern from *: + """ + #include + #if defined(__FreeBSD__) || defined(__APPLE__) + #define DIRENT_D_OFF(d) 0UL + #else + #define DIRENT_D_OFF(d) ((d)->d_off) + #endif + """ + # Declare struct with common fields + cdef struct dirent: + long int d_ino + unsigned short int d_reclen + unsigned char d_type + char d_name[256] + # Note: d_off only on Linux - use DIRENT_D_OFF macro to access + + # Macro to get d_off portably + unsigned long DIRENT_D_OFF(dirent *d) + cdef extern from "../include/platform_errno.h": ctypedef signed int int32_t; int32_t ceph_to_hostos_errno(int32_t e) diff --git a/src/pybind/cephfs/cephfs.pyx b/src/pybind/cephfs/cephfs.pyx index 1d8fc2282ea..7a3b4668d7e 100644 --- a/src/pybind/cephfs/cephfs.pyx +++ b/src/pybind/cephfs/cephfs.pyx @@ -300,6 +300,8 @@ cdef class DirResult(object): return False def readdir(self): + cdef dirent *dirent + self.lib.require_state("mounted") with nogil: @@ -307,20 +309,12 @@ cdef class DirResult(object): if not dirent: return None - IF UNAME_SYSNAME == "FreeBSD" or UNAME_SYSNAME == "Darwin": - return DirEntry(d_ino=dirent.d_ino, - d_off=0, - d_reclen=dirent.d_reclen, - d_type=dirent.d_type, - d_name=dirent.d_name, - d_snapid=CEPH_NOSNAP) - ELSE: - return DirEntry(d_ino=dirent.d_ino, - d_off=dirent.d_off, - d_reclen=dirent.d_reclen, - d_type=dirent.d_type, - d_name=dirent.d_name, - d_snapid=CEPH_NOSNAP) + return DirEntry(d_ino=dirent.d_ino, + d_off=DIRENT_D_OFF(dirent), + d_reclen=dirent.d_reclen, + d_type=dirent.d_type, + d_name=dirent.d_name, + d_snapid=CEPH_NOSNAP) def close(self): if self.handle: @@ -383,20 +377,12 @@ cdef class SnapDiffHandle(object): if ret == 0: return None - IF UNAME_SYSNAME == "FreeBSD" or UNAME_SYSNAME == "Darwin": - return DirEntry(d_ino=difent.dir_entry.d_ino, - d_off=0, - d_reclen=difent.dir_entry.d_reclen, - d_type=difent.dir_entry.d_type, - d_name=difent.dir_entry.d_name, - d_snapid=difent.snapid) - ELSE: - return DirEntry(d_ino=difent.dir_entry.d_ino, - d_off=difent.dir_entry.d_off, - d_reclen=difent.dir_entry.d_reclen, - d_type=difent.dir_entry.d_type, - d_name=difent.dir_entry.d_name, - d_snapid=difent.snapid) + return DirEntry(d_ino=difent.dir_entry.d_ino, + d_off=DIRENT_D_OFF(&difent.dir_entry), + d_reclen=difent.dir_entry.d_reclen, + d_type=difent.dir_entry.d_type, + d_name=difent.dir_entry.d_name, + d_snapid=difent.snapid) def close(self): if (not self.opened): diff --git a/src/pybind/cephfs/mock_cephfs.pxi b/src/pybind/cephfs/mock_cephfs.pxi index 717d6e468bb..006575c9a85 100644 --- a/src/pybind/cephfs/mock_cephfs.pxi +++ b/src/pybind/cephfs/mock_cephfs.pxi @@ -9,6 +9,28 @@ cdef: pass +cdef extern from *: + """ + // Mock dirent struct and DIRENT_D_OFF macro for BUILD_DOC + struct dirent { + long int d_ino; + unsigned short int d_reclen; + unsigned char d_type; + char d_name[256]; + }; + #define DIRENT_D_OFF(d) 0UL + """ + # dirent struct for mock (matches declaration in c_cephfs.pxd) + cdef struct dirent: + long int d_ino + unsigned short int d_reclen + unsigned char d_type + char d_name[256] + + # Macro to get d_off portably (always returns 0 in mock) + unsigned long DIRENT_D_OFF(dirent *d) + + cdef: cdef struct statx "ceph_statx": uint32_t stx_mask @@ -48,7 +70,8 @@ cdef nogil: int dummy cdef struct ceph_snapdiff_entry_t: - int dummy + dirent dir_entry + uint64_t snapid ctypedef void* rados_t diff --git a/src/pybind/cephfs/types.pxd b/src/pybind/cephfs/types.pxd index cbe31cbf4ba..d4f3db9202a 100644 --- a/src/pybind/cephfs/types.pxd +++ b/src/pybind/cephfs/types.pxd @@ -40,18 +40,3 @@ cdef extern from "": void *iov_base size_t iov_len -IF UNAME_SYSNAME == "FreeBSD" or UNAME_SYSNAME == "Darwin": - cdef extern from "dirent.h": - cdef struct dirent: - long int d_ino - unsigned short int d_reclen - unsigned char d_type - char d_name[256] -ELSE: - cdef extern from "dirent.h": - cdef struct dirent: - long int d_ino - unsigned long int d_off - unsigned short int d_reclen - unsigned char d_type - char d_name[256] -- 2.47.3