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 <kzak@redhat.com>
diff --git a/libblkid/docs/libblkid-sections.txt b/libblkid/docs/libblkid-sections.txt index 60a43b5..75b2b3a 100644 --- a/libblkid/docs/libblkid-sections.txt +++ b/libblkid/docs/libblkid-sections.txt
@@ -62,6 +62,7 @@ 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 8dfea21..adfd3c3 100644 --- a/libblkid/src/blkid.h.in +++ b/libblkid/src/blkid.h.in
@@ -243,6 +243,25 @@ 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 753dbb5..66ef69a 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 *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 01b6170..cf520d9 100644 --- a/libblkid/src/libblkid.sym +++ b/libblkid/src/libblkid.sym
@@ -194,4 +194,5 @@ 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 45691f4..3464a37 100644 --- a/libblkid/src/probe.c +++ b/libblkid/src/probe.c
@@ -2245,6 +2245,45 @@ } /** + * 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 *