summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorCorinna Vinschen <corinna@vinschen.de>2005-12-14 15:54:33 +0000
committerCorinna Vinschen <corinna@vinschen.de>2005-12-14 15:54:33 +0000
commite3d14af155fb84890a32fad7f7706967ac5bc7d9 (patch)
tree05df3064a2c24a1542e182a3aa2d5ff4e3df8f56
parent10cba930d401056aed4b2fb360b5e084d61ecabb (diff)
downloadcygnal-e3d14af155fb84890a32fad7f7706967ac5bc7d9.tar.gz
cygnal-e3d14af155fb84890a32fad7f7706967ac5bc7d9.tar.bz2
cygnal-e3d14af155fb84890a32fad7f7706967ac5bc7d9.zip
* fhandler.cc (fhandler_base::open_9x): Handle O_SYNC and O_DIRECT
flags. (fhandler_base::open): Ditto. * fhandler_floppy.cc (fhandler_dev_floppy::open): Don't allocate devbuf in O_DIRECT case. * fhandler_raw.cc (fhandler_dev_raw::ioctl): Don't allow buffer changes in O_DIRECT case. Allow returning a buffer size 0, which indicates O_DIRECT. * fhandler_tape.cc (fhandler_dev_tape::open): Use O_SYNC flag to hand down the !buffer_writes case. Don't allocate devbuf in O_DIRECT case. (fhandler_dev_tape::raw_read): Don't mess with devbuf if it's NULL. * include/fcntl.h: Define _FDIRECT, O_DIRECT, O_DSYNC and O_RSYNC. * include/cygwin/version.h: Bump API minor version.
-rw-r--r--winsup/cygwin/ChangeLog17
-rw-r--r--winsup/cygwin/fhandler.cc14
-rw-r--r--winsup/cygwin/fhandler_floppy.cc7
-rw-r--r--winsup/cygwin/fhandler_raw.cc8
-rw-r--r--winsup/cygwin/fhandler_tape.cc141
-rw-r--r--winsup/cygwin/include/cygwin/version.h3
-rw-r--r--winsup/cygwin/include/fcntl.h9
7 files changed, 124 insertions, 75 deletions
diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog
index f4aa368fd..2591eab4d 100644
--- a/winsup/cygwin/ChangeLog
+++ b/winsup/cygwin/ChangeLog
@@ -1,3 +1,20 @@
+2005-12-14 Corinna Vinschen <corinna@vinschen.de>
+
+ * fhandler.cc (fhandler_base::open_9x): Handle O_SYNC and O_DIRECT
+ flags.
+ (fhandler_base::open): Ditto.
+ * fhandler_floppy.cc (fhandler_dev_floppy::open): Don't allocate devbuf
+ in O_DIRECT case.
+ * fhandler_raw.cc (fhandler_dev_raw::ioctl): Don't allow buffer
+ changes in O_DIRECT case. Allow returning a buffer size 0, which
+ indicates O_DIRECT.
+ * fhandler_tape.cc (fhandler_dev_tape::open): Use O_SYNC flag to
+ hand down the !buffer_writes case. Don't allocate devbuf in O_DIRECT
+ case.
+ (fhandler_dev_tape::raw_read): Don't mess with devbuf if it's NULL.
+ * include/fcntl.h: Define _FDIRECT, O_DIRECT, O_DSYNC and O_RSYNC.
+ * include/cygwin/version.h: Bump API minor version.
+
2005-12-13 Christopher Faylor <cgf@timesys.com>
* cygtls.cc (_cygtls::remove): Don't bother if we're exiting.
diff --git a/winsup/cygwin/fhandler.cc b/winsup/cygwin/fhandler.cc
index 6931cb6bc..0a119c845 100644
--- a/winsup/cygwin/fhandler.cc
+++ b/winsup/cygwin/fhandler.cc
@@ -492,6 +492,10 @@ fhandler_base::open_9x (int flags, mode_t mode)
file_attributes = FILE_ATTRIBUTE_NORMAL;
if (flags & O_DIROPEN)
file_attributes |= FILE_FLAG_BACKUP_SEMANTICS;
+ if (flags & O_SYNC)
+ file_attributes |= FILE_FLAG_WRITE_THROUGH;
+ if (flags & O_DIRECT)
+ file_attributes |= FILE_FLAG_NO_BUFFERING;
if (get_major () == DEV_SERIAL_MAJOR)
file_attributes |= FILE_FLAG_OVERLAPPED;
@@ -599,18 +603,16 @@ fhandler_base::open (int flags, mode_t mode)
break;
default:
create_options = 0;
- if (get_major () == DEV_TAPE_MAJOR && (flags & O_TEXT))
- {
- /* O_TEXT is used to indicate write-through on tape devices */
- create_options |= FILE_WRITE_THROUGH;
- flags &= ~O_TEXT;
- }
if ((flags & (O_RDONLY | O_WRONLY | O_RDWR)) == O_RDONLY)
access = GENERIC_READ;
else if ((flags & (O_RDONLY | O_WRONLY | O_RDWR)) == O_WRONLY)
access = GENERIC_WRITE | FILE_READ_ATTRIBUTES;
else
access = GENERIC_READ | GENERIC_WRITE;
+ if (flags & O_SYNC)
+ create_options |= FILE_WRITE_THROUGH;
+ if (flags & O_DIRECT)
+ create_options |= FILE_NO_INTERMEDIATE_BUFFERING;
if (get_major () != DEV_SERIAL_MAJOR && get_major () != DEV_TAPE_MAJOR)
{
create_options |= FILE_SYNCHRONOUS_IO_NONALERT;
diff --git a/winsup/cygwin/fhandler_floppy.cc b/winsup/cygwin/fhandler_floppy.cc
index 3bc9f5191..a8b99b266 100644
--- a/winsup/cygwin/fhandler_floppy.cc
+++ b/winsup/cygwin/fhandler_floppy.cc
@@ -161,9 +161,10 @@ fhandler_dev_floppy::open (int flags, mode_t)
relatively big value increases performance by means. The new ioctl call
with 'rdevio.h' header file supports changing this value.
- Let's try to be smart: Let's take a multiple of typical tar and cpio
- buffer sizes by default. */
- devbufsiz = 61440L;
+ As default buffer size, we're using some value which is a multiple of
+ the typical tar and cpio buffer sizes, Except O_DIRECT is set, in which
+ case we're not buffering at all. */
+ devbufsiz = (flags & O_DIRECT) ? 0L : 61440L;
int ret = fhandler_dev_raw::open (flags);
if (ret && get_drive_info (NULL))
diff --git a/winsup/cygwin/fhandler_raw.cc b/winsup/cygwin/fhandler_raw.cc
index 00d023e7e..0cfb51e6c 100644
--- a/winsup/cygwin/fhandler_raw.cc
+++ b/winsup/cygwin/fhandler_raw.cc
@@ -159,12 +159,14 @@ fhandler_dev_raw::ioctl (unsigned int cmd, void *buf)
}
else if ((devbuf && ((op->rd_parm <= 1 && (devbufend - devbufstart))
|| op->rd_parm < devbufend - devbufstart))
- || (op->rd_parm > 1 && (op->rd_parm % 512)))
+ || (op->rd_parm > 1 && (op->rd_parm % 512))
+ || (get_flags () & O_DIRECT))
/* The conditions for a *valid* parameter are these:
- If there's still data in the current buffer, it must
fit in the new buffer.
- The new size is either 0 or 1, both indicating unbufferd
- I/O, or the new buffersize must be a multiple of 512. */
+ I/O, or the new buffersize must be a multiple of 512.
+ - In the O_DIRECT case, the whole request is invalid. */
ret = ERROR_INVALID_PARAMETER;
else if (!devbuf || op->rd_parm != devbufsiz)
{
@@ -198,7 +200,7 @@ fhandler_dev_raw::ioctl (unsigned int cmd, void *buf)
if (!get)
ret = ERROR_INVALID_PARAMETER;
else
- get->bufsiz = devbufsiz ?: 1L;
+ get->bufsiz = devbufsiz;
}
else
return fhandler_base::ioctl (cmd, buf);
diff --git a/winsup/cygwin/fhandler_tape.cc b/winsup/cygwin/fhandler_tape.cc
index d3fd3eee2..0b4e53773 100644
--- a/winsup/cygwin/fhandler_tape.cc
+++ b/winsup/cygwin/fhandler_tape.cc
@@ -1216,11 +1216,16 @@ fhandler_dev_tape::open (int flags, mode_t)
__seterrno ();
return 0;
}
- /* The O_TEXT flag is used to indicate write-through (non buffered writes)
- to the underlying fhandler_dev_raw::open call. */
- flags &= ~O_TEXT;
+
+ /* The O_SYNC flag is not supported by the tape driver. Use the
+ MT_ST_BUFFER_WRITES and MT_ST_ASYNC_WRITES flags in the drive
+ settings instead. In turn, the MT_ST_BUFFER_WRITES is translated
+ into O_SYNC, which controls the FILE_WRITE_THROUGH flag in the
+ NtCreateFile call in fhandler_base::open. */
+ flags &= ~O_SYNC;
if (!mt->drive (driveno ())->buffer_writes ())
- flags |= O_TEXT;
+ flags |= O_SYNC;
+
ret = fhandler_dev_raw::open (flags);
if (ret)
{
@@ -1231,8 +1236,11 @@ fhandler_dev_tape::open (int flags, mode_t)
mt->drive (driveno ())->set_pos (get_handle (),
TAPE_SPACE_FILEMARKS, 1, true);
- devbufsiz = mt->drive (driveno ())->dp ()->MaximumBlockSize;
- devbuf = new char [devbufsiz];
+ if (!(flags & O_DIRECT))
+ {
+ devbufsiz = mt->drive (driveno ())->dp ()->MaximumBlockSize;
+ devbuf = new char [devbufsiz];
+ }
devbufstart = devbufend = 0;
}
else
@@ -1283,70 +1291,81 @@ fhandler_dev_tape::raw_read (void *ptr, size_t &ulen)
return;
}
block_size = mt->drive (driveno ())->mp ()->BlockSize;
- if (devbufend > devbufstart)
+ if (devbuf)
{
- bytes_to_read = min (len, devbufend - devbufstart);
- debug_printf ("read %d bytes from buffer (rest %d)",
- bytes_to_read, devbufend - devbufstart - bytes_to_read);
- memcpy (buf, devbuf + devbufstart, bytes_to_read);
- len -= bytes_to_read;
- bytes_read += bytes_to_read;
- buf += bytes_to_read;
- devbufstart += bytes_to_read;
- if (devbufstart == devbufend)
- devbufstart = devbufend = 0;
- /* If a switch to variable block_size occured, just return the buffer
- remains until the buffer is empty, then proceed with usual variable
- block size handling (one block per read call). */
- if (!block_size)
- len = 0;
- }
- if (len > 0)
- {
- if (!mt_evt && !(mt_evt = CreateEvent (&sec_none, TRUE, FALSE, NULL)))
- debug_printf ("Creating event failed, %E");
- size_t block_fit = !block_size ? len : rounddown(len, block_size);
- if (block_fit)
+ if (devbufend > devbufstart)
{
- debug_printf ("read %d bytes from tape (rest %d)",
- block_fit, len - block_fit);
- ret = mt->drive (driveno ())->read (get_handle (), mt_evt, buf,
- block_fit);
- if (ret)
- __seterrno_from_win_error (ret);
- else if (block_fit)
- {
- len -= block_fit;
- bytes_read += block_fit;
- buf += block_fit;
- /* Only one block in each read call, please. */
- if (!block_size)
- len = 0;
- }
- else {
+ bytes_to_read = min (len, devbufend - devbufstart);
+ debug_printf ("read %d bytes from buffer (rest %d)",
+ bytes_to_read, devbufend - devbufstart - bytes_to_read);
+ memcpy (buf, devbuf + devbufstart, bytes_to_read);
+ len -= bytes_to_read;
+ bytes_read += bytes_to_read;
+ buf += bytes_to_read;
+ devbufstart += bytes_to_read;
+ if (devbufstart == devbufend)
+ devbufstart = devbufend = 0;
+ /* If a switch to variable block_size occured, just return the buffer
+ remains until the buffer is empty, then proceed with usual variable
+ block size handling (one block per read call). */
+ if (!block_size)
len = 0;
- if (bytes_read)
- lastblk_to_read (true);
- }
}
- if (!ret && len > 0)
+ if (len > 0)
{
- debug_printf ("read %d bytes from tape (one block)", block_size);
- ret = mt->drive (driveno ())->read (get_handle (), mt_evt, devbuf,
- block_size);
- if (ret)
- __seterrno_from_win_error (ret);
- else if (block_size)
+ if (!mt_evt && !(mt_evt = CreateEvent (&sec_none, TRUE, FALSE, NULL)))
+ debug_printf ("Creating event failed, %E");
+ size_t block_fit = !block_size ? len : rounddown(len, block_size);
+ if (block_fit)
+ {
+ debug_printf ("read %d bytes from tape (rest %d)",
+ block_fit, len - block_fit);
+ ret = mt->drive (driveno ())->read (get_handle (), mt_evt, buf,
+ block_fit);
+ if (ret)
+ __seterrno_from_win_error (ret);
+ else if (block_fit)
+ {
+ len -= block_fit;
+ bytes_read += block_fit;
+ buf += block_fit;
+ /* Only one block in each read call, please. */
+ if (!block_size)
+ len = 0;
+ }
+ else {
+ len = 0;
+ if (bytes_read)
+ lastblk_to_read (true);
+ }
+ }
+ if (!ret && len > 0)
{
- devbufstart = len;
- devbufend = block_size;
- bytes_read += len;
- memcpy (buf, devbuf, len);
+ debug_printf ("read %d bytes from tape (one block)", block_size);
+ ret = mt->drive (driveno ())->read (get_handle (), mt_evt, devbuf,
+ block_size);
+ if (ret)
+ __seterrno_from_win_error (ret);
+ else if (block_size)
+ {
+ devbufstart = len;
+ devbufend = block_size;
+ bytes_read += len;
+ memcpy (buf, devbuf, len);
+ }
+ else if (bytes_read)
+ lastblk_to_read (true);
}
- else if (bytes_read)
- lastblk_to_read (true);
}
}
+ else
+ {
+ if (!mt_evt && !(mt_evt = CreateEvent (&sec_none, TRUE, FALSE, NULL)))
+ debug_printf ("Creating event failed, %E");
+ bytes_read = ulen;
+ ret = mt->drive (driveno ())->read (get_handle (), mt_evt, ptr,
+ bytes_read);
+ }
ulen = (ret ? (size_t) -1 : bytes_read);
unlock ();
}
diff --git a/winsup/cygwin/include/cygwin/version.h b/winsup/cygwin/include/cygwin/version.h
index db65e43a4..048b06e9d 100644
--- a/winsup/cygwin/include/cygwin/version.h
+++ b/winsup/cygwin/include/cygwin/version.h
@@ -282,12 +282,13 @@ details. */
for this?
147: Eliminate problematic d_ino from dirent structure. unsetenv now returns
int, as per linux.
+ 148: Add open(2) flags O_SYNC, O_RSYNC, O_DSYNC and O_DIRECT.
*/
/* Note that we forgot to bump the api for ualarm, strtoll, strtoull */
#define CYGWIN_VERSION_API_MAJOR 0
-#define CYGWIN_VERSION_API_MINOR 147
+#define CYGWIN_VERSION_API_MINOR 148
/* There is also a compatibity version number associated with the
shared memory regions. It is incremented when incompatible
diff --git a/winsup/cygwin/include/fcntl.h b/winsup/cygwin/include/fcntl.h
index 774966e9a..33b0692b3 100644
--- a/winsup/cygwin/include/fcntl.h
+++ b/winsup/cygwin/include/fcntl.h
@@ -1,6 +1,6 @@
/* fcntl.h
- Copyright 1996, 1998, 2001 Red Hat, Inc.
+ Copyright 1996, 1998, 2001, 2005 Red Hat, Inc.
This file is part of Cygwin.
@@ -14,4 +14,11 @@ details. */
#include <sys/fcntl.h>
#define O_NDELAY _FNDELAY
+/* sys/fcntl defines values up to 0x40000 (O_NOINHERIT). */
+#define _FDIRECT 0x80000
+
+#define O_DIRECT _FDIRECT
+#define O_DSYNC _FSYNC
+#define O_RSYNC _FSYNC
+
#endif /* _FCNTL_H */