From owner-freebsd-hackers@freebsd.org Sun Jul 24 03:04:51 2016 Return-Path: Delivered-To: freebsd-hackers@mailman.ysv.freebsd.org Received: from mx1.freebsd.org (mx1.freebsd.org [IPv6:2001:1900:2254:206a::19:1]) by mailman.ysv.freebsd.org (Postfix) with ESMTP id 537C9B9B640 for ; Sun, 24 Jul 2016 03:04:51 +0000 (UTC) (envelope-from freebsd-hackers@m.gmane.org) Received: from plane.gmane.org (plane.gmane.org [80.91.229.3]) (using TLSv1 with cipher AES256-SHA (256/256 bits)) (Client did not present a certificate) by mx1.freebsd.org (Postfix) with ESMTPS id 1A1291CF6 for ; Sun, 24 Jul 2016 03:04:50 +0000 (UTC) (envelope-from freebsd-hackers@m.gmane.org) Received: from list by plane.gmane.org with local (Exim 4.69) (envelope-from ) id 1bR9iZ-0008HS-Tl for freebsd-hackers@freebsd.org; Sun, 24 Jul 2016 05:04:40 +0200 Received: from ip184-189-249-34.sb.sd.cox.net ([184.189.249.34]) by main.gmane.org with esmtp (Gmexim 0.1 (Debian)) id 1AlnuQ-0007hv-00 for ; Sun, 24 Jul 2016 05:04:39 +0200 Received: from julian by ip184-189-249-34.sb.sd.cox.net with local (Gmexim 0.1 (Debian)) id 1AlnuQ-0007hv-00 for ; Sun, 24 Jul 2016 05:04:39 +0200 X-Injected-Via-Gmane: http://gmane.org/ To: freebsd-hackers@freebsd.org From: Julian Hsiao Subject: fsync(1) patch to do DIOCGFLUSH on character devices Date: Sun, 24 Jul 2016 03:04:34 +0000 (UTC) Lines: 95 Message-ID: Mime-Version: 1.0 Content-Type: text/plain; charset=us-ascii Content-Transfer-Encoding: 7bit X-Complaints-To: usenet@ger.gmane.org X-Gmane-NNTP-Posting-Host: sea.gmane.org User-Agent: Loom/3.14 (http://gmane.org/) X-Loom-IP: 184.189.249.34 (Mozilla/5.0 (Macintosh; Intel Mac OS X 10.11; rv:48.0) Gecko/20100101 Firefox/48.0) X-BeenThere: freebsd-hackers@freebsd.org X-Mailman-Version: 2.1.22 Precedence: list List-Id: Technical Discussions relating to FreeBSD List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , X-List-Received-Date: Sun, 24 Jul 2016 03:04:51 -0000 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 #include #include +#include +#include +#include +#include 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); }