fsync(1) patch to do DIOCGFLUSH on character devices

Julian Hsiao julian at hsiao.email
Sun Jul 24 03:04:51 UTC 2016


Hi,

The fsync(1) utility is a simple wrapper around fsync(2), but I didn't find
a similar utility for calling ioctl(DIOCGFLUSH) for character devices.
fsync(2) is a no-op on character device files, which is a little surprising
but makes sense I suppose (would raising EINVAL be against POSIX?).

However, conceptually the goal is the same: commit writes to permanent
storage, so here's a small patch to fsync(1) that calls ioctl(DIOCGFLUSH)
for character device files instead.

Incidentally, turns out you need to open character device files with O_RDWR
(or maybe O_WRONLY is enough, I didn't check) for DIOCGFLUSH, but fsync(2)
only needs O_RDONLY for plain files. This seems a little odd; does anyone
know why?

Julian Hsiao

Index: usr.bin/fsync/fsync.1
===================================================================
diff --git a/head/usr.bin/fsync/fsync.1 b/head/usr.bin/fsync/fsync.1
--- a/head/usr.bin/fsync/fsync.1	(revision 303213)
+++ b/head/usr.bin/fsync/fsync.1	(working copy)
@@ -44,6 +44,8 @@
 .Nm
 utility uses the
 .Xr fsync 2
+or the
+.Xr ioctl 2
 function call.
 .Sh EXIT STATUS
 If an error occurs, the
Index: usr.bin/fsync/fsync.c
===================================================================
diff --git a/head/usr.bin/fsync/fsync.c b/head/usr.bin/fsync/fsync.c
--- a/head/usr.bin/fsync/fsync.c	(revision 303213)
+++ b/head/usr.bin/fsync/fsync.c	(working copy)
@@ -35,6 +35,10 @@
 #include <stdlib.h>
 #include <sysexits.h>
 #include <unistd.h>
+#include <string.h>
+#include <sys/stat.h>
+#include <sys/disk.h>
+#include <sys/ioctl.h>
 
 static void	usage(void);
 
@@ -44,6 +48,7 @@
 	int fd;
 	int i;
 	int rval;
+	struct stat sb;
 	
 	if (argc < 2) {
 		usage();
@@ -58,11 +63,35 @@
 				rval = EX_NOINPUT;
 			continue;
 		}
+		memset(&sb, 0, sizeof(sb));
+		if (fstat(fd, &sb) == -1) {
+			warn("fstat %s", argv[i]);
+			rval = EX_OSERR;
+			continue;
+		}
 
-		if (fsync(fd) == -1) {
-			warn("fsync %s", argv[i]);
-			if (rval == EX_OK)
+		if (S_ISCHR(sb.st_mode)) {
+			if (close(fd) == -1) {
+				warn("close %s", argv[i]);
 				rval = EX_OSERR;
+				continue;
+			}
+			if ((fd = open(argv[i], O_RDWR)) == -1) {
+				warn("open %s", argv[i]);
+				rval = EX_NOINPUT;
+				continue;
+			}			
+		
+			if (ioctl(fd, DIOCGFLUSH) == -1) {
+				warn("ioctl %s", argv[i]);
+				rval = EX_OSERR;
+			}
+		} else {
+			if (fsync(fd) == -1) {
+				warn("fsync %s", argv[i]);
+				if (rval == EX_OK)
+					rval = EX_OSERR;
+			}
 		}
 		close(fd);
 	}



More information about the freebsd-hackers mailing list