]> git.ipfire.org Git - thirdparty/util-linux.git/commitdiff
libblkid: reopen floppy without O_NONBLOCK
authorKarel Zak <kzak@redhat.com>
Mon, 17 Jan 2022 11:37:13 +0000 (12:37 +0100)
committerKarel Zak <kzak@redhat.com>
Thu, 20 Jan 2022 09:12:21 +0000 (10:12 +0100)
Vladimir Sementsov-Ogievskiy wrote:
> The commit "floppy: reintroduce O_NDELAY fix" was removed from kernel,
> so we faced the bug described and discussed here:
> https://bugzilla.suse.com/show_bug.cgi?id=3D1181018
>
> Discussion in kernel list on reverting the commit:
> https://www.spinics.net/lists/stable/msg493061.html
>
> In short, I can quote Jiri Kosina's comment:
>
>   opening floppy device node with O_NONBLOCK is asking for all kinds
>   of trouble
>
> So opening floppy with O_NONBLOCK in blkid leads to failure of blkid,
> probable failure of mount and unpleasant error messages in dmesg (see
> also patch 02 for details).

Based on patch from Vladimir.

CC: Jiri Kosina <jkosina@suse.cz>
Reported-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
Reviewed-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
Tested-by: Vladimir Sementsov-Ogievskiy <vsementsov@virtuozzo.com>
Signed-off-by: Karel Zak <kzak@redhat.com>
include/fileutils.h
lib/fileutils.c
libblkid/src/probe.c

index c36ce6353735d3d839b1cd0099b2628f0406361c..8722ed59bb659771d1fd2561b24621b27b0c4584 100644 (file)
@@ -97,4 +97,7 @@ extern void ul_close_all_fds(unsigned int first, unsigned int last);
 #define UL_COPY_WRITE_ERROR (-2)
 int ul_copy_file(int from, int to);
 
+
+extern int ul_reopen(int fd, int flags);
+
 #endif /* UTIL_LINUX_FILEUTILS */
index 7a8fce26f0c700672337acbfdb3c74dcc76f56e0..cce3e352acb1e2612930941c3e0acc4406682079 100644 (file)
@@ -288,3 +288,22 @@ int ul_copy_file(int from, int to)
        return copy_file_simple(from, to);
 #endif
 }
+
+int ul_reopen(int fd, int flags)
+{
+       ssize_t ssz;
+       char buf[PATH_MAX];
+       char fdpath[ sizeof(_PATH_PROC_FDDIR) + sizeof(stringify_value(INT_MAX)) ];
+
+       snprintf(fdpath, sizeof(fdpath), _PATH_PROC_FDDIR "/%d", fd);
+
+       ssz = readlink(fdpath, buf, sizeof(buf) - 1);
+       if (ssz < 0)
+               return -errno;
+
+       assert(ssz > 0);
+
+       buf[ssz] = '\0';
+
+       return open(buf, flags);
+}
index 6168370e2f64cec4013bae60d2b9a47b61f5c14c..7fb4cf64144578f7d767c6399a3892ed07e93818 100644 (file)
 #ifdef HAVE_ERRNO_H
 #include <errno.h>
 #endif
+#ifdef HAVE_LINUX_FD_H
+#include <linux/fd.h>
+#endif
 #include <inttypes.h>
 #include <stdint.h>
 #include <stdarg.h>
 #include "sysfs.h"
 #include "strutils.h"
 #include "list.h"
+#include "fileutils.h"
 
 /*
  * All supported chains
@@ -907,6 +911,35 @@ int blkid_probe_set_device(blkid_probe pr, int fd,
        if (fd < 0)
                return 1;
 
+#ifdef FDGETFDCSTAT
+       {
+               /*
+                * Re-open without O_NONBLOCK for floppy device.
+                *
+                * Since kernel commit c7e9d0020361f4308a70cdfd6d5335e273eb8717
+                * floppy drive works bad when opened with O_NONBLOCK.
+                */
+               struct floppy_fdc_state flst;
+
+               if (ioctl(fd, FDGETFDCSTAT, &flst) >= 0) {
+                       int flags = fcntl(fd, F_GETFL, 0);
+
+                       if (flags < 0)
+                               goto err;
+                       if (flags & O_NONBLOCK) {
+                               flags &= ~O_NONBLOCK;
+
+                               fd = ul_reopen(fd, flags | O_CLOEXEC);
+                               if (fd < 0)
+                                       goto err;
+
+                               pr->flags |= BLKID_FL_PRIVATE_FD;
+                               pr->fd = fd;
+                       }
+               }
+       }
+#endif
+
 #if defined(POSIX_FADV_RANDOM) && defined(HAVE_POSIX_FADVISE)
        /* Disable read-ahead */
        posix_fadvise(fd, 0, 0, POSIX_FADV_RANDOM);