]> git.ipfire.org Git - thirdparty/util-linux.git/commitdiff
libblkid: use VFS I/O operations in probe
authorKarel Zak <kzak@redhat.com>
Tue, 30 Jun 2026 12:47:19 +0000 (14:47 +0200)
committerKarel Zak <kzak@redhat.com>
Thu, 9 Jul 2026 10:18:04 +0000 (12:18 +0200)
Replace all direct I/O syscalls in the probe path with ul_vfs_*
dispatch functions that route through the pluggable VFS layer when
set, falling back to real syscalls otherwise.

Add ul_vfs_copy() to include/vfs.h for cloning VFS ops structs.

Changed call sites:
 - read_buffer(): lseek + read
 - is_sector_readable(): lseek + read, changed signature to take
   blkid_probe instead of bare fd
 - blkid_probe_set_device(): close
 - blkid_do_wipe(): lseek + write_all + fsync
 - blkid_free_probe(): close + free(pr->vfs)
 - blkid_clone_probe(): allocate private VFS copy via ul_vfs_copy()

Addresses: https://github.com/util-linux/util-linux/issues/4308
Signed-off-by: Karel Zak <kzak@redhat.com>
include/vfs.h
libblkid/src/probe.c
libblkid/src/topology/md.c

index 9dfab596feb25264351480d5cc6a2ea3731b613b..97479ec0aa7af15715e1af72d6216c0ac9654290 100644 (file)
@@ -5,6 +5,7 @@
 #ifndef UTIL_LINUX_VFS_H
 #define UTIL_LINUX_VFS_H
 
+#include <stdlib.h>
 #include <unistd.h>
 #include <fcntl.h>
 #include <sys/types.h>
@@ -37,6 +38,19 @@ static inline void ul_vfs_init(struct ul_vfs_ops *dst,
        dst->size = sizeof(*dst);
 }
 
+static inline struct ul_vfs_ops *ul_vfs_copy(const struct ul_vfs_ops *src)
+{
+       struct ul_vfs_ops *dst;
+
+       if (!src)
+               return NULL;
+       dst = malloc(sizeof(*dst));
+       if (!dst)
+               return NULL;
+       memcpy(dst, src, sizeof(*dst));
+       return dst;
+}
+
 static inline ssize_t ul_vfs_read(const struct ul_vfs_ops *vfs,
                                  int fd, void *buf, size_t count)
 {
index 3464a3736e89e1b6198077d4192549dbd1a40fad..6fa8ba563c76f10ceaa33ca3546f1666db973975 100644 (file)
@@ -194,6 +194,14 @@ blkid_probe blkid_clone_probe(blkid_probe parent)
 
        pr->flags &= ~BLKID_FL_PRIVATE_FD;
 
+       if (parent->vfs) {
+               pr->vfs = ul_vfs_copy(parent->vfs);
+               if (!pr->vfs) {
+                       blkid_free_probe(pr);
+                       return NULL;
+               }
+       }
+
        return pr;
 }
 
@@ -277,13 +285,14 @@ void blkid_free_probe(blkid_probe pr)
        }
 
        if ((pr->flags & BLKID_FL_PRIVATE_FD) && pr->fd >= 0)
-               close(pr->fd);
+               ul_vfs_close(pr->vfs, pr->fd);
        blkid_probe_reset_buffers(pr);
        blkid_probe_reset_values(pr);
        blkid_probe_reset_hints(pr);
        blkid_free_probe(pr->disk_probe);
 
        DBG(LOWPROBE, ul_debug("free probe"));
+       free(pr->vfs);
        free(pr);
 }
 
@@ -578,7 +587,7 @@ static struct blkid_bufinfo *read_buffer(blkid_probe pr, uint64_t real_off, uint
        ssize_t ret;
        struct blkid_bufinfo *bf = NULL;
 
-       if (lseek(pr->fd, real_off, SEEK_SET) == (off_t) -1) {
+       if (ul_vfs_lseek(pr->vfs, pr->fd, real_off, SEEK_SET) == (off_t) -1) {
                errno = 0;
                return NULL;
        }
@@ -611,7 +620,7 @@ static struct blkid_bufinfo *read_buffer(blkid_probe pr, uint64_t real_off, uint
        DBG(LOWPROBE, ul_debug("\tread: off=%"PRIu64" len=%"PRIu64"",
                               real_off, len));
 
-       ret = read(pr->fd, bf->data, len);
+       ret = ul_vfs_read(pr->vfs, pr->fd, bf->data, len);
        if (ret != (ssize_t) len) {
                DBG(LOWPROBE, ul_debug("\tread failed: %m"));
                remove_buffer(bf);
@@ -967,15 +976,15 @@ int blkdid_probe_is_opal_locked(blkid_probe pr)
 
 #ifdef CDROM_GET_CAPABILITY
 
-static int is_sector_readable(int fd, uint64_t sector)
+static int is_sector_readable(blkid_probe pr, uint64_t sector)
 {
        char buf[512];
        ssize_t sz;
 
-       if (lseek(fd, sector * 512, SEEK_SET) == (off_t) -1)
+       if (ul_vfs_lseek(pr->vfs, pr->fd, sector * 512, SEEK_SET) == (off_t) -1)
                goto failed;
 
-       sz = read(fd, buf, sizeof(buf));
+       sz = ul_vfs_read(pr->vfs, pr->fd, buf, sizeof(buf));
        if (sz != (ssize_t) sizeof(buf))
                goto failed;
 
@@ -1002,7 +1011,7 @@ static void cdrom_size_correction(blkid_probe pr, uint64_t last_written)
                nsectors = (last_written+1) << 2;
 
        for (n = nsectors - 12; n < nsectors; n++) {
-               if (!is_sector_readable(pr->fd, n))
+               if (!is_sector_readable(pr, n))
                        goto failed;
        }
 
@@ -1073,7 +1082,7 @@ int blkid_probe_set_device(blkid_probe pr, int fd,
        blkid_probe_reset_buffers(pr);
 
        if ((pr->flags & BLKID_FL_PRIVATE_FD) && pr->fd >= 0)
-               close(pr->fd);
+               ul_vfs_close(pr->vfs, pr->fd);
 
        if (pr->disk_probe) {
                blkid_free_probe(pr->disk_probe);
@@ -1614,7 +1623,7 @@ int blkid_do_wipe(blkid_probe pr, int dryrun)
            "do_wipe [offset=0x%"PRIx64" (%"PRIu64"), len=%zu, chain=%s, idx=%d, dryrun=%s]\n",
            offset, offset, len, chn->driver->name, chn->idx, dryrun ? "yes" : "not"));
 
-       if (lseek(fd, offset, SEEK_SET) == (off_t) -1)
+       if (ul_vfs_lseek(pr->vfs, fd, offset, SEEK_SET) == (off_t) -1)
                return BLKID_PROBE_ERROR;
 
        if (!dryrun && len) {
@@ -1622,9 +1631,9 @@ int blkid_do_wipe(blkid_probe pr, int dryrun)
                        memset(buf, 0, len);
 
                        /* wipen on device */
-                       if (ul_write_all(fd, buf, len))
+                       if (ul_vfs_write_all(pr->vfs, fd, buf, len))
                                return BLKID_PROBE_ERROR;
-                       if (fsync(fd) != 0)
+                       if (ul_vfs_fsync(pr->vfs, fd) != 0)
                                return BLKID_PROBE_ERROR;
                } else {
 #ifdef HAVE_LINUX_BLKZONED_H
index b9e7d792f2b0e32bcb611dae49dcc801fe0bc71a..4d9c01884a96aa9fe2f4df2b0412e72342914d8a 100644 (file)
@@ -97,7 +97,7 @@ static int probe_md_tp(blkid_probe pr,
                if (!diskpath)
                        goto nothing;
 
-               fd = open(diskpath, O_RDONLY|O_CLOEXEC);
+               fd = ul_vfs_open(pr->vfs, diskpath, O_RDONLY|O_CLOEXEC, 0);
                free(diskpath);
 
                 if (fd == -1)
@@ -110,7 +110,7 @@ static int probe_md_tp(blkid_probe pr,
                goto nothing;
 
        if (fd >= 0 && fd != pr->fd) {
-               close(fd);
+               ul_vfs_close(pr->vfs, fd);
                fd = -1;
        }