From: Karel Zak Date: Tue, 30 Jun 2026 12:38:56 +0000 (+0200) Subject: libblkid: add blkid_probe_set_vfs() for pluggable I/O X-Git-Url: http://git.ipfire.org/cgi-bin/gitweb.cgi?a=commitdiff_plain;h=19db6c490cc7f753f6af191a7818e8ca1767d52d;p=thirdparty%2Futil-linux.git libblkid: add blkid_probe_set_vfs() for pluggable I/O Add public API to set custom VFS I/O operations on a blkid probe. This allows callers (e.g., systemd fibers) to replace standard read/write/lseek/open/close/fsync with custom implementations. The ops struct is copied into a private allocation owned by the probe. NULL function pointers fall back to standard syscalls. Passing NULL resets to defaults. New public symbol: blkid_probe_set_vfs() New struct in public header: struct ul_vfs_ops (with include guard shared with include/vfs.h) Addresses: https://github.com/util-linux/util-linux/issues/4308 Signed-off-by: Karel Zak --- diff --git a/libblkid/docs/libblkid-sections.txt b/libblkid/docs/libblkid-sections.txt index 60a43b502..75b2b3a32 100644 --- a/libblkid/docs/libblkid-sections.txt +++ b/libblkid/docs/libblkid-sections.txt @@ -62,6 +62,7 @@ blkid_probe_reset_hints blkid_probe_set_device blkid_probe_set_hint blkid_probe_set_sectorsize +blkid_probe_set_vfs blkid_probe_step_back blkid_reset_probe BLKID_PROBE_OK diff --git a/libblkid/src/blkid.h.in b/libblkid/src/blkid.h.in index 8dfea2152..adfd3c3a6 100644 --- a/libblkid/src/blkid.h.in +++ b/libblkid/src/blkid.h.in @@ -243,6 +243,25 @@ extern int blkid_probe_set_device(blkid_probe pr, int fd, blkid_loff_t off, blkid_loff_t size) __ul_attribute__((nonnull)); +#ifndef UL_VFS_OPS_DEFINED +#define UL_VFS_OPS_DEFINED + +struct ul_vfs_ops { + size_t size; + + ssize_t (*vfs_read)(int fd, void *buf, size_t count); + ssize_t (*vfs_write)(int fd, const void *buf, size_t count); + int (*vfs_open)(const char *pathname, int flags, mode_t mode); + int (*vfs_close)(int fd); + off_t (*vfs_lseek)(int fd, off_t offset, int whence); + int (*vfs_fsync)(int fd); +}; + +#endif /* UL_VFS_OPS_DEFINED */ + +extern int blkid_probe_set_vfs(blkid_probe pr, const struct ul_vfs_ops *ops) + __ul_attribute__((nonnull(1))); + extern dev_t blkid_probe_get_devno(blkid_probe pr) __ul_attribute__((nonnull)); diff --git a/libblkid/src/blkidP.h b/libblkid/src/blkidP.h index 753dbb58f..66ef69a8a 100644 --- a/libblkid/src/blkidP.h +++ b/libblkid/src/blkidP.h @@ -32,6 +32,7 @@ #include "blkdev.h" #include "debug.h" +#include "vfs.h" #include "blkid.h" #include "list.h" #include "encode.h" @@ -232,6 +233,8 @@ struct blkid_struct_probe struct blkid_struct_probe *parent; /* for clones */ struct blkid_struct_probe *disk_probe; /* whole-disk probing */ + + struct ul_vfs_ops *vfs; /* pluggable I/O ops (owned, or NULL) */ }; /* private flags library flags */ diff --git a/libblkid/src/libblkid.sym b/libblkid/src/libblkid.sym index 01b6170f9..cf520d9b7 100644 --- a/libblkid/src/libblkid.sym +++ b/libblkid/src/libblkid.sym @@ -194,4 +194,5 @@ BLKID_2_40 { BLKID_2_43 { blkid_evaluate_tag2; + blkid_probe_set_vfs; } BLKID_2_40; diff --git a/libblkid/src/probe.c b/libblkid/src/probe.c index 45691f4ad..3464a3736 100644 --- a/libblkid/src/probe.c +++ b/libblkid/src/probe.c @@ -2244,6 +2244,45 @@ int blkid_probe_set_sectorsize(blkid_probe pr, unsigned int sz) return 0; } +/** + * blkid_probe_set_vfs: + * @pr: probe + * @ops: VFS operations or NULL to reset to defaults + * + * Sets custom I/O operations for the probe. This allows replacing + * standard read/write/lseek/etc. with custom implementations + * (e.g., fiber-aware I/O). + * + * The @ops struct is copied into a private allocation owned by the + * probe. The caller sets ops->size to sizeof(struct ul_vfs_ops) to + * enable forward/backward compatibility. NULL function pointers fall + * back to standard syscalls. Passing @ops as NULL frees the private + * copy and resets the probe to default (direct syscall) I/O. + * + * Note: blkid_new_probe_from_filename() opens the device before VFS + * can be set. VFS users should use blkid_new_probe(), then + * blkid_probe_set_vfs(), then blkid_probe_open_device(). + * + * Since: 2.43 + * + * Returns: 0 on success, or <0 in case of error. + */ +int blkid_probe_set_vfs(blkid_probe pr, const struct ul_vfs_ops *ops) +{ + if (!ops) { + free(pr->vfs); + pr->vfs = NULL; + return 0; + } + if (!pr->vfs) { + pr->vfs = calloc(1, sizeof(*pr->vfs)); + if (!pr->vfs) + return -ENOMEM; + } + ul_vfs_init(pr->vfs, ops); + return 0; +} + /** * blkid_probe_get_sectors: * @pr: probe