diff options
author | Corinna Vinschen <corinna@vinschen.de> | 2005-12-14 15:54:33 +0000 |
---|---|---|
committer | Corinna Vinschen <corinna@vinschen.de> | 2005-12-14 15:54:33 +0000 |
commit | e3d14af155fb84890a32fad7f7706967ac5bc7d9 (patch) | |
tree | 05df3064a2c24a1542e182a3aa2d5ff4e3df8f56 | |
parent | 10cba930d401056aed4b2fb360b5e084d61ecabb (diff) | |
download | newlib-e3d14af155fb84890a32fad7f7706967ac5bc7d9.zip newlib-e3d14af155fb84890a32fad7f7706967ac5bc7d9.tar.gz newlib-e3d14af155fb84890a32fad7f7706967ac5bc7d9.tar.bz2 |
* 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/ChangeLog | 17 | ||||
-rw-r--r-- | winsup/cygwin/fhandler.cc | 14 | ||||
-rw-r--r-- | winsup/cygwin/fhandler_floppy.cc | 7 | ||||
-rw-r--r-- | winsup/cygwin/fhandler_raw.cc | 8 | ||||
-rw-r--r-- | winsup/cygwin/fhandler_tape.cc | 141 | ||||
-rw-r--r-- | winsup/cygwin/include/cygwin/version.h | 3 | ||||
-rw-r--r-- | winsup/cygwin/include/fcntl.h | 9 |
7 files changed, 124 insertions, 75 deletions
diff --git a/winsup/cygwin/ChangeLog b/winsup/cygwin/ChangeLog index f4aa368..2591eab 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 6931cb6..0a119c8 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 3bc9f51..a8b99b2 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 00d023e..0cfb51e 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 d3fd3ee..0b4e537 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 db65e43..048b06e 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 774966e..33b0692 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 */ |