* 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.
This commit is contained in:
parent
10cba930d4
commit
e3d14af155
|
@ -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>
|
2005-12-13 Christopher Faylor <cgf@timesys.com>
|
||||||
|
|
||||||
* cygtls.cc (_cygtls::remove): Don't bother if we're exiting.
|
* cygtls.cc (_cygtls::remove): Don't bother if we're exiting.
|
||||||
|
|
|
@ -492,6 +492,10 @@ fhandler_base::open_9x (int flags, mode_t mode)
|
||||||
file_attributes = FILE_ATTRIBUTE_NORMAL;
|
file_attributes = FILE_ATTRIBUTE_NORMAL;
|
||||||
if (flags & O_DIROPEN)
|
if (flags & O_DIROPEN)
|
||||||
file_attributes |= FILE_FLAG_BACKUP_SEMANTICS;
|
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)
|
if (get_major () == DEV_SERIAL_MAJOR)
|
||||||
file_attributes |= FILE_FLAG_OVERLAPPED;
|
file_attributes |= FILE_FLAG_OVERLAPPED;
|
||||||
|
|
||||||
|
@ -599,18 +603,16 @@ fhandler_base::open (int flags, mode_t mode)
|
||||||
break;
|
break;
|
||||||
default:
|
default:
|
||||||
create_options = 0;
|
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)
|
if ((flags & (O_RDONLY | O_WRONLY | O_RDWR)) == O_RDONLY)
|
||||||
access = GENERIC_READ;
|
access = GENERIC_READ;
|
||||||
else if ((flags & (O_RDONLY | O_WRONLY | O_RDWR)) == O_WRONLY)
|
else if ((flags & (O_RDONLY | O_WRONLY | O_RDWR)) == O_WRONLY)
|
||||||
access = GENERIC_WRITE | FILE_READ_ATTRIBUTES;
|
access = GENERIC_WRITE | FILE_READ_ATTRIBUTES;
|
||||||
else
|
else
|
||||||
access = GENERIC_READ | GENERIC_WRITE;
|
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)
|
if (get_major () != DEV_SERIAL_MAJOR && get_major () != DEV_TAPE_MAJOR)
|
||||||
{
|
{
|
||||||
create_options |= FILE_SYNCHRONOUS_IO_NONALERT;
|
create_options |= FILE_SYNCHRONOUS_IO_NONALERT;
|
||||||
|
|
|
@ -161,9 +161,10 @@ fhandler_dev_floppy::open (int flags, mode_t)
|
||||||
relatively big value increases performance by means. The new ioctl call
|
relatively big value increases performance by means. The new ioctl call
|
||||||
with 'rdevio.h' header file supports changing this value.
|
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
|
As default buffer size, we're using some value which is a multiple of
|
||||||
buffer sizes by default. */
|
the typical tar and cpio buffer sizes, Except O_DIRECT is set, in which
|
||||||
devbufsiz = 61440L;
|
case we're not buffering at all. */
|
||||||
|
devbufsiz = (flags & O_DIRECT) ? 0L : 61440L;
|
||||||
int ret = fhandler_dev_raw::open (flags);
|
int ret = fhandler_dev_raw::open (flags);
|
||||||
|
|
||||||
if (ret && get_drive_info (NULL))
|
if (ret && get_drive_info (NULL))
|
||||||
|
|
|
@ -159,12 +159,14 @@ fhandler_dev_raw::ioctl (unsigned int cmd, void *buf)
|
||||||
}
|
}
|
||||||
else if ((devbuf && ((op->rd_parm <= 1 && (devbufend - devbufstart))
|
else if ((devbuf && ((op->rd_parm <= 1 && (devbufend - devbufstart))
|
||||||
|| op->rd_parm < 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:
|
/* The conditions for a *valid* parameter are these:
|
||||||
- If there's still data in the current buffer, it must
|
- If there's still data in the current buffer, it must
|
||||||
fit in the new buffer.
|
fit in the new buffer.
|
||||||
- The new size is either 0 or 1, both indicating unbufferd
|
- 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;
|
ret = ERROR_INVALID_PARAMETER;
|
||||||
else if (!devbuf || op->rd_parm != devbufsiz)
|
else if (!devbuf || op->rd_parm != devbufsiz)
|
||||||
{
|
{
|
||||||
|
@ -198,7 +200,7 @@ fhandler_dev_raw::ioctl (unsigned int cmd, void *buf)
|
||||||
if (!get)
|
if (!get)
|
||||||
ret = ERROR_INVALID_PARAMETER;
|
ret = ERROR_INVALID_PARAMETER;
|
||||||
else
|
else
|
||||||
get->bufsiz = devbufsiz ?: 1L;
|
get->bufsiz = devbufsiz;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
return fhandler_base::ioctl (cmd, buf);
|
return fhandler_base::ioctl (cmd, buf);
|
||||||
|
|
|
@ -1216,11 +1216,16 @@ fhandler_dev_tape::open (int flags, mode_t)
|
||||||
__seterrno ();
|
__seterrno ();
|
||||||
return 0;
|
return 0;
|
||||||
}
|
}
|
||||||
/* The O_TEXT flag is used to indicate write-through (non buffered writes)
|
|
||||||
to the underlying fhandler_dev_raw::open call. */
|
/* The O_SYNC flag is not supported by the tape driver. Use the
|
||||||
flags &= ~O_TEXT;
|
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 ())
|
if (!mt->drive (driveno ())->buffer_writes ())
|
||||||
flags |= O_TEXT;
|
flags |= O_SYNC;
|
||||||
|
|
||||||
ret = fhandler_dev_raw::open (flags);
|
ret = fhandler_dev_raw::open (flags);
|
||||||
if (ret)
|
if (ret)
|
||||||
{
|
{
|
||||||
|
@ -1231,8 +1236,11 @@ fhandler_dev_tape::open (int flags, mode_t)
|
||||||
mt->drive (driveno ())->set_pos (get_handle (),
|
mt->drive (driveno ())->set_pos (get_handle (),
|
||||||
TAPE_SPACE_FILEMARKS, 1, true);
|
TAPE_SPACE_FILEMARKS, 1, true);
|
||||||
|
|
||||||
devbufsiz = mt->drive (driveno ())->dp ()->MaximumBlockSize;
|
if (!(flags & O_DIRECT))
|
||||||
devbuf = new char [devbufsiz];
|
{
|
||||||
|
devbufsiz = mt->drive (driveno ())->dp ()->MaximumBlockSize;
|
||||||
|
devbuf = new char [devbufsiz];
|
||||||
|
}
|
||||||
devbufstart = devbufend = 0;
|
devbufstart = devbufend = 0;
|
||||||
}
|
}
|
||||||
else
|
else
|
||||||
|
@ -1283,69 +1291,80 @@ fhandler_dev_tape::raw_read (void *ptr, size_t &ulen)
|
||||||
return;
|
return;
|
||||||
}
|
}
|
||||||
block_size = mt->drive (driveno ())->mp ()->BlockSize;
|
block_size = mt->drive (driveno ())->mp ()->BlockSize;
|
||||||
if (devbufend > devbufstart)
|
if (devbuf)
|
||||||
{
|
{
|
||||||
bytes_to_read = min (len, devbufend - devbufstart);
|
if (devbufend > devbufstart)
|
||||||
debug_printf ("read %d bytes from buffer (rest %d)",
|
{
|
||||||
bytes_to_read, devbufend - devbufstart - bytes_to_read);
|
bytes_to_read = min (len, devbufend - devbufstart);
|
||||||
memcpy (buf, devbuf + devbufstart, bytes_to_read);
|
debug_printf ("read %d bytes from buffer (rest %d)",
|
||||||
len -= bytes_to_read;
|
bytes_to_read, devbufend - devbufstart - bytes_to_read);
|
||||||
bytes_read += bytes_to_read;
|
memcpy (buf, devbuf + devbufstart, bytes_to_read);
|
||||||
buf += bytes_to_read;
|
len -= bytes_to_read;
|
||||||
devbufstart += bytes_to_read;
|
bytes_read += bytes_to_read;
|
||||||
if (devbufstart == devbufend)
|
buf += bytes_to_read;
|
||||||
devbufstart = devbufend = 0;
|
devbufstart += bytes_to_read;
|
||||||
/* If a switch to variable block_size occured, just return the buffer
|
if (devbufstart == devbufend)
|
||||||
remains until the buffer is empty, then proceed with usual variable
|
devbufstart = devbufend = 0;
|
||||||
block size handling (one block per read call). */
|
/* If a switch to variable block_size occured, just return the buffer
|
||||||
if (!block_size)
|
remains until the buffer is empty, then proceed with usual variable
|
||||||
len = 0;
|
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)
|
||||||
|
{
|
||||||
|
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)
|
||||||
|
{
|
||||||
|
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);
|
||||||
|
}
|
||||||
|
}
|
||||||
}
|
}
|
||||||
if (len > 0)
|
else
|
||||||
{
|
{
|
||||||
if (!mt_evt && !(mt_evt = CreateEvent (&sec_none, TRUE, FALSE, NULL)))
|
if (!mt_evt && !(mt_evt = CreateEvent (&sec_none, TRUE, FALSE, NULL)))
|
||||||
debug_printf ("Creating event failed, %E");
|
debug_printf ("Creating event failed, %E");
|
||||||
size_t block_fit = !block_size ? len : rounddown(len, block_size);
|
bytes_read = ulen;
|
||||||
if (block_fit)
|
ret = mt->drive (driveno ())->read (get_handle (), mt_evt, ptr,
|
||||||
{
|
bytes_read);
|
||||||
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)
|
|
||||||
{
|
|
||||||
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);
|
|
||||||
}
|
|
||||||
}
|
}
|
||||||
ulen = (ret ? (size_t) -1 : bytes_read);
|
ulen = (ret ? (size_t) -1 : bytes_read);
|
||||||
unlock ();
|
unlock ();
|
||||||
|
|
|
@ -282,12 +282,13 @@ details. */
|
||||||
for this?
|
for this?
|
||||||
147: Eliminate problematic d_ino from dirent structure. unsetenv now returns
|
147: Eliminate problematic d_ino from dirent structure. unsetenv now returns
|
||||||
int, as per linux.
|
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 */
|
/* Note that we forgot to bump the api for ualarm, strtoll, strtoull */
|
||||||
|
|
||||||
#define CYGWIN_VERSION_API_MAJOR 0
|
#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
|
/* There is also a compatibity version number associated with the
|
||||||
shared memory regions. It is incremented when incompatible
|
shared memory regions. It is incremented when incompatible
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
/* fcntl.h
|
/* fcntl.h
|
||||||
|
|
||||||
Copyright 1996, 1998, 2001 Red Hat, Inc.
|
Copyright 1996, 1998, 2001, 2005 Red Hat, Inc.
|
||||||
|
|
||||||
This file is part of Cygwin.
|
This file is part of Cygwin.
|
||||||
|
|
||||||
|
@ -14,4 +14,11 @@ details. */
|
||||||
#include <sys/fcntl.h>
|
#include <sys/fcntl.h>
|
||||||
#define O_NDELAY _FNDELAY
|
#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 */
|
#endif /* _FCNTL_H */
|
||||||
|
|
Loading…
Reference in New Issue