* 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:
Corinna Vinschen 2005-12-14 15:54:33 +00:00
parent 10cba930d4
commit e3d14af155
7 changed files with 127 additions and 78 deletions

View File

@ -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.

View File

@ -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;

View File

@ -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))

View File

@ -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);

View File

@ -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 ();

View File

@ -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

View File

@ -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 */