mirror of
git://sourceware.org/git/newlib-cygwin.git
synced 2025-01-18 12:29:32 +08:00
* fhandler.h (class fhandler_dev_raw): Add members devbufalloc and
devbufalign. (class fhandler_dev_floppy): Remove member bytes_per_sector; * fhandler_floppy.cc (bytes_per_sector): Define as devbufalign. (fhandler_dev_floppy::open): Set devbufalign to a multiple of the sector size and handle devbuf allocation and alignment in !O_DIRECT case here. Change comment accordingly. Call FSCTL_ALLOW_EXTENDED_DASD_IO for partitions as well. (fhandler_dev_floppy::raw_write): Fix comment. Rewrite and fix writing behaviour when application uses read and lseek. (fhandler_dev_floppy::lseek): Use rounddown macro. Call SetFilePointerEx rather than the old SetFilePointer. (fhandler_dev_floppy::ioctl): Reformat switch. Call IOCTL_DISK_UPDATE_PROPERTIES rather than IOCTL_DISK_UPDATE_DRIVE_SIZE in BLKRRPART case. Support BLKIOMIN, BLKIOOPT, BLKPBSZGET and BLKALIGNOFF. * fhandler_raw.cc (fhandler_dev_raw::fhandler_dev_raw): Initialize all devbuf-related members. (fhandler_dev_raw::~fhandler_dev_raw): Delete devbufalloc rather than devbuf. (fhandler_dev_raw::open): Drop allocating devbuf. (fhandler_dev_raw::dup): Allocate devbufalloc and set devbuf to support new sector-aligned devbuf handling. (fhandler_dev_raw::fixup_after_exec): Ditto. * fhandler_tape.cc (fhandler_dev_tape::open): Ditto, set devbufalign to 1. * include/cygwin/fs.h (BLKIOMIN): Define. (BLKIOOPT): Define. (BLKALIGNOFF): Define. (BLKPBSZGET): Define.
This commit is contained in:
parent
93c9cdc1b0
commit
db8224e8be
@ -1,3 +1,36 @@
|
||||
2012-10-13 Corinna Vinschen <corinna@vinschen.de>
|
||||
|
||||
* fhandler.h (class fhandler_dev_raw): Add members devbufalloc and
|
||||
devbufalign.
|
||||
(class fhandler_dev_floppy): Remove member bytes_per_sector;
|
||||
* fhandler_floppy.cc (bytes_per_sector): Define as devbufalign.
|
||||
(fhandler_dev_floppy::open): Set devbufalign to a multiple of the
|
||||
sector size and handle devbuf allocation and alignment in !O_DIRECT
|
||||
case here. Change comment accordingly.
|
||||
Call FSCTL_ALLOW_EXTENDED_DASD_IO for partitions as well.
|
||||
(fhandler_dev_floppy::raw_write): Fix comment. Rewrite and fix
|
||||
writing behaviour when application uses read and lseek.
|
||||
(fhandler_dev_floppy::lseek): Use rounddown macro. Call
|
||||
SetFilePointerEx rather than the old SetFilePointer.
|
||||
(fhandler_dev_floppy::ioctl): Reformat switch. Call
|
||||
IOCTL_DISK_UPDATE_PROPERTIES rather than IOCTL_DISK_UPDATE_DRIVE_SIZE
|
||||
in BLKRRPART case. Support BLKIOMIN, BLKIOOPT, BLKPBSZGET and
|
||||
BLKALIGNOFF.
|
||||
* fhandler_raw.cc (fhandler_dev_raw::fhandler_dev_raw): Initialize
|
||||
all devbuf-related members.
|
||||
(fhandler_dev_raw::~fhandler_dev_raw): Delete devbufalloc rather than
|
||||
devbuf.
|
||||
(fhandler_dev_raw::open): Drop allocating devbuf.
|
||||
(fhandler_dev_raw::dup): Allocate devbufalloc and set devbuf to support
|
||||
new sector-aligned devbuf handling.
|
||||
(fhandler_dev_raw::fixup_after_exec): Ditto.
|
||||
* fhandler_tape.cc (fhandler_dev_tape::open): Ditto, set devbufalign
|
||||
to 1.
|
||||
* include/cygwin/fs.h (BLKIOMIN): Define.
|
||||
(BLKIOOPT): Define.
|
||||
(BLKALIGNOFF): Define.
|
||||
(BLKPBSZGET): Define.
|
||||
|
||||
2012-10-12 Corinna Vinschen <corinna@vinschen.de>
|
||||
|
||||
* fhandler_raw.cc (fhandler_dev_raw::open): Allow O_EXCL flag, as on
|
||||
|
@ -798,7 +798,9 @@ class fhandler_mailslot : public fhandler_base_overlapped
|
||||
class fhandler_dev_raw: public fhandler_base
|
||||
{
|
||||
protected:
|
||||
char *devbufalloc;
|
||||
char *devbuf;
|
||||
size_t devbufalign;
|
||||
size_t devbufsiz;
|
||||
size_t devbufstart;
|
||||
size_t devbufend;
|
||||
@ -856,7 +858,6 @@ class fhandler_dev_floppy: public fhandler_dev_raw
|
||||
{
|
||||
private:
|
||||
_off64_t drive_size;
|
||||
unsigned long bytes_per_sector;
|
||||
part_t *partitions;
|
||||
struct status_flags
|
||||
{
|
||||
|
@ -28,6 +28,8 @@ details. */
|
||||
|| (err) == ERROR_SEEK \
|
||||
|| (err) == ERROR_SECTOR_NOT_FOUND)
|
||||
|
||||
#define bytes_per_sector devbufalign
|
||||
|
||||
/**********************************************************************/
|
||||
/* fhandler_dev_floppy */
|
||||
|
||||
@ -355,16 +357,6 @@ fhandler_dev_floppy::write_file (const void *buf, DWORD to_write,
|
||||
int
|
||||
fhandler_dev_floppy::open (int flags, mode_t)
|
||||
{
|
||||
/* The correct size of the buffer would be 512 bytes, which is the atomic
|
||||
size, supported by WinNT. Unfortunately, the performance is worse than
|
||||
access to file system on same device! Setting buffer size to a
|
||||
relatively big value increases performance by means. The new ioctl call
|
||||
with 'rdevio.h' header file supports changing this value.
|
||||
|
||||
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)
|
||||
@ -376,11 +368,22 @@ fhandler_dev_floppy::open (int flags, mode_t)
|
||||
close ();
|
||||
return 0;
|
||||
}
|
||||
if (!(flags & O_DIRECT))
|
||||
{
|
||||
/* Create sector-aligned buffer. As default buffer size, we're using
|
||||
some big, sector-aligned value. Since direct blockdev IO is
|
||||
usually non-buffered and non-cached, the performance without
|
||||
buffering is worse than access to a file system on same device.
|
||||
Whoever uses O_DIRECT has my condolences. */
|
||||
devbufsiz = MAX (16 * bytes_per_sector, 65536);
|
||||
devbufalloc = new char [devbufsiz + devbufalign];
|
||||
devbuf = (char *) roundup2 ((uintptr_t) devbufalloc, devbufalign);
|
||||
}
|
||||
|
||||
/* If we're trying to access a CD/DVD drive, or an entire disk,
|
||||
make sure we're actually allowed to read *all* of the device.
|
||||
This is actually documented in the MSDN CreateFile man page. */
|
||||
if (get_major () != DEV_FLOPPY_MAJOR
|
||||
&& (get_major () == DEV_CDROM_MAJOR || get_minor () % 16 == 0)
|
||||
&& !DeviceIoControl (get_handle (), FSCTL_ALLOW_EXTENDED_DASD_IO,
|
||||
NULL, 0, NULL, 0, &bytes_read, NULL))
|
||||
debug_printf ("DeviceIoControl (FSCTL_ALLOW_EXTENDED_DASD_IO) "
|
||||
@ -562,34 +565,103 @@ fhandler_dev_floppy::raw_write (const void *ptr, size_t len)
|
||||
char *p = (char *) ptr;
|
||||
int ret;
|
||||
|
||||
/* Checking a previous end of media on tape */
|
||||
/* Checking a previous end of media */
|
||||
if (eom_detected ())
|
||||
{
|
||||
set_errno (ENOSPC);
|
||||
return -1;
|
||||
}
|
||||
|
||||
/* Invalidate buffer. */
|
||||
devbufstart = devbufend = 0;
|
||||
if (!len)
|
||||
return 0;
|
||||
|
||||
if (len > 0)
|
||||
if (devbuf)
|
||||
{
|
||||
if (!write_file (p, len, &bytes_written, &ret))
|
||||
{
|
||||
if (!IS_EOM (ret))
|
||||
DWORD cplen, written;
|
||||
|
||||
/* First check if we have an active read buffer. If so, try to fit in
|
||||
the start of the input buffer and write out the entire result.
|
||||
This also covers the situation after lseek since lseek fills the read
|
||||
buffer in case we seek to an address which is not sector aligned. */
|
||||
if (devbufend && devbufstart < devbufend)
|
||||
{
|
||||
_off64_t current_pos = get_current_position ();
|
||||
cplen = MIN (len, devbufend - devbufstart);
|
||||
memcpy (devbuf + devbufstart, p, cplen);
|
||||
LARGE_INTEGER off = { QuadPart:current_pos - devbufend };
|
||||
if (!SetFilePointerEx (get_handle (), off, NULL, FILE_BEGIN))
|
||||
{
|
||||
devbufstart = devbufend = 0;
|
||||
__seterrno ();
|
||||
return -1;
|
||||
}
|
||||
eom_detected (true);
|
||||
if (!bytes_written)
|
||||
if (!write_file (devbuf, devbufend, &written, &ret))
|
||||
{
|
||||
set_errno (ENOSPC);
|
||||
return -1;
|
||||
devbufstart = devbufend = 0;
|
||||
goto err;
|
||||
}
|
||||
/* Align pointers, lengths, etc. */
|
||||
cplen = MIN (cplen, written);
|
||||
devbufstart += cplen;
|
||||
p += cplen;
|
||||
len -= cplen;
|
||||
bytes_written += cplen;
|
||||
if (len)
|
||||
devbufstart = devbufend = 0;
|
||||
}
|
||||
/* As long as there's still something left in the input buffer ... */
|
||||
while (len)
|
||||
{
|
||||
/* Compute the length to write. The problem is that the underlying
|
||||
driver may require sector aligned read/write. So we copy the data
|
||||
over to devbuf, which is guaranteed to be sector aligned. */
|
||||
cplen = MIN (len, devbufsiz);
|
||||
if (cplen >= bytes_per_sector)
|
||||
/* If the remaining len is >= sector size, write out the maximum
|
||||
possible multiple of the sector size which fits into devbuf. */
|
||||
cplen = rounddown (cplen, bytes_per_sector);
|
||||
else
|
||||
{
|
||||
/* If len < sector size, read in the next sector, seek back,
|
||||
and just copy the new data over the old one before writing. */
|
||||
LARGE_INTEGER off = { QuadPart:get_current_position () };
|
||||
if (!read_file (devbuf, bytes_per_sector, &written, &ret))
|
||||
goto err;
|
||||
if (!SetFilePointerEx (get_handle (), off, NULL, FILE_BEGIN))
|
||||
{
|
||||
__seterrno ();
|
||||
return -1;
|
||||
}
|
||||
}
|
||||
memcpy (devbuf, p, cplen);
|
||||
if (!write_file (devbuf, MAX (cplen, bytes_per_sector), &written,
|
||||
&ret))
|
||||
{
|
||||
bytes_written += MIN (cplen, written);
|
||||
goto err;
|
||||
}
|
||||
cplen = MIN (cplen, written);
|
||||
p += cplen;
|
||||
len -= cplen;
|
||||
bytes_written += cplen;
|
||||
}
|
||||
return bytes_written;
|
||||
}
|
||||
return bytes_written;
|
||||
|
||||
/* In O_DIRECT case, just write. */
|
||||
if (write_file (p, len, &bytes_written, &ret))
|
||||
return bytes_written;
|
||||
|
||||
err:
|
||||
if (IS_EOM (ret))
|
||||
{
|
||||
eom_detected (true);
|
||||
if (!bytes_written)
|
||||
set_errno (ENOSPC);
|
||||
}
|
||||
else if (!bytes_written)
|
||||
__seterrno ();
|
||||
return bytes_written ?: -1;
|
||||
}
|
||||
|
||||
_off64_t
|
||||
@ -631,20 +703,14 @@ fhandler_dev_floppy::lseek (_off64_t offset, int whence)
|
||||
}
|
||||
}
|
||||
|
||||
sector_aligned_offset.QuadPart = (lloffset / bytes_per_sector)
|
||||
* bytes_per_sector;
|
||||
sector_aligned_offset.QuadPart = rounddown (lloffset, bytes_per_sector);
|
||||
bytes_left = lloffset - sector_aligned_offset.QuadPart;
|
||||
|
||||
/* Invalidate buffer. */
|
||||
devbufstart = devbufend = 0;
|
||||
|
||||
sector_aligned_offset.LowPart =
|
||||
SetFilePointer (get_handle (),
|
||||
sector_aligned_offset.LowPart,
|
||||
§or_aligned_offset.HighPart,
|
||||
FILE_BEGIN);
|
||||
if (sector_aligned_offset.LowPart == INVALID_SET_FILE_POINTER
|
||||
&& GetLastError ())
|
||||
if (!SetFilePointerEx (get_handle (), sector_aligned_offset, NULL,
|
||||
FILE_BEGIN))
|
||||
{
|
||||
__seterrno ();
|
||||
return -1;
|
||||
@ -665,59 +731,69 @@ fhandler_dev_floppy::lseek (_off64_t offset, int whence)
|
||||
int
|
||||
fhandler_dev_floppy::ioctl (unsigned int cmd, void *buf)
|
||||
{
|
||||
DISK_GEOMETRY di;
|
||||
int ret = 0;
|
||||
DWORD bytes_read;
|
||||
|
||||
switch (cmd)
|
||||
{
|
||||
case HDIO_GETGEO:
|
||||
{
|
||||
debug_printf ("HDIO_GETGEO");
|
||||
return get_drive_info ((struct hd_geometry *) buf);
|
||||
}
|
||||
debug_printf ("HDIO_GETGEO");
|
||||
ret = get_drive_info ((struct hd_geometry *) buf);
|
||||
break;
|
||||
case BLKGETSIZE:
|
||||
case BLKGETSIZE64:
|
||||
{
|
||||
debug_printf ("BLKGETSIZE");
|
||||
if (cmd == BLKGETSIZE)
|
||||
*(long *)buf = drive_size >> 9UL;
|
||||
else
|
||||
*(_off64_t *)buf = drive_size;
|
||||
return 0;
|
||||
}
|
||||
debug_printf ("BLKGETSIZE");
|
||||
if (cmd == BLKGETSIZE)
|
||||
*(long *)buf = drive_size >> 9UL;
|
||||
else
|
||||
*(_off64_t *)buf = drive_size;
|
||||
break;
|
||||
case BLKRRPART:
|
||||
{
|
||||
debug_printf ("BLKRRPART");
|
||||
if (!DeviceIoControl (get_handle (),
|
||||
IOCTL_DISK_UPDATE_DRIVE_SIZE,
|
||||
NULL, 0,
|
||||
&di, sizeof (di),
|
||||
&bytes_read, NULL))
|
||||
{
|
||||
__seterrno ();
|
||||
return -1;
|
||||
}
|
||||
debug_printf ("BLKRRPART");
|
||||
if (!DeviceIoControl (get_handle (), IOCTL_DISK_UPDATE_PROPERTIES,
|
||||
NULL, 0, NULL, 0, &bytes_read, NULL))
|
||||
{
|
||||
__seterrno ();
|
||||
ret = -1;
|
||||
}
|
||||
else
|
||||
get_drive_info (NULL);
|
||||
return 0;
|
||||
}
|
||||
break;
|
||||
case BLKSSZGET:
|
||||
{
|
||||
debug_printf ("BLKSSZGET");
|
||||
*(int *)buf = bytes_per_sector;
|
||||
return 0;
|
||||
}
|
||||
debug_printf ("BLKSSZGET");
|
||||
*(int *)buf = bytes_per_sector;
|
||||
break;
|
||||
case BLKIOMIN:
|
||||
debug_printf ("BLKIOMIN");
|
||||
*(int *)buf = bytes_per_sector;
|
||||
break;
|
||||
case BLKIOOPT:
|
||||
debug_printf ("BLKIOOPT");
|
||||
*(int *)buf = bytes_per_sector;
|
||||
break;
|
||||
case BLKPBSZGET:
|
||||
debug_printf ("BLKPBSZGET");
|
||||
*(int *)buf = bytes_per_sector;
|
||||
break;
|
||||
case BLKALIGNOFF:
|
||||
debug_printf ("BLKALIGNOFF");
|
||||
*(int *)buf = 0;
|
||||
break;
|
||||
case RDSETBLK:
|
||||
/* Just check the restriction that blocksize must be a multiple
|
||||
of the sector size of the underlying volume sector size,
|
||||
then fall through to fhandler_dev_raw::ioctl. */
|
||||
debug_printf ("RDSETBLK");
|
||||
if (((struct rdop *) buf)->rd_parm % bytes_per_sector)
|
||||
{
|
||||
SetLastError (ERROR_INVALID_PARAMETER);
|
||||
__seterrno ();
|
||||
set_errno (EINVAL);
|
||||
return -1;
|
||||
}
|
||||
/*FALLTHRU*/
|
||||
default:
|
||||
return fhandler_dev_raw::ioctl (cmd, buf);
|
||||
ret = fhandler_dev_raw::ioctl (cmd, buf);
|
||||
break;
|
||||
}
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -13,6 +13,7 @@
|
||||
|
||||
#include <cygwin/rdevio.h>
|
||||
#include <sys/mtio.h>
|
||||
#include <sys/param.h>
|
||||
#include "cygerrno.h"
|
||||
#include "path.h"
|
||||
#include "fhandler.h"
|
||||
@ -21,7 +22,14 @@
|
||||
/* fhandler_dev_raw */
|
||||
|
||||
fhandler_dev_raw::fhandler_dev_raw ()
|
||||
: fhandler_base (), status ()
|
||||
: fhandler_base (),
|
||||
devbufalloc (NULL),
|
||||
devbuf (NULL),
|
||||
devbufalign (0),
|
||||
devbufsiz (0),
|
||||
devbufstart (0),
|
||||
devbufend (0),
|
||||
status ()
|
||||
{
|
||||
need_fork_fixup (true);
|
||||
}
|
||||
@ -29,7 +37,7 @@ fhandler_dev_raw::fhandler_dev_raw ()
|
||||
fhandler_dev_raw::~fhandler_dev_raw ()
|
||||
{
|
||||
if (devbufsiz > 1L)
|
||||
delete [] devbuf;
|
||||
delete [] devbufalloc;
|
||||
}
|
||||
|
||||
int __stdcall
|
||||
@ -74,8 +82,6 @@ fhandler_dev_raw::open (int flags, mode_t)
|
||||
flags = ((flags & ~O_WRONLY) | O_RDWR);
|
||||
|
||||
int res = fhandler_base::open (flags, 0);
|
||||
if (res && devbufsiz > 1L)
|
||||
devbuf = new char [devbufsiz];
|
||||
|
||||
return res;
|
||||
}
|
||||
@ -90,7 +96,12 @@ fhandler_dev_raw::dup (fhandler_base *child, int flags)
|
||||
fhandler_dev_raw *fhc = (fhandler_dev_raw *) child;
|
||||
|
||||
if (devbufsiz > 1L)
|
||||
fhc->devbuf = new char [devbufsiz];
|
||||
{
|
||||
/* Create sector-aligned buffer */
|
||||
fhc->devbufalloc = new char [devbufsiz + devbufalign];
|
||||
fhc->devbuf = (char *) roundup2 ((uintptr_t) fhc->devbufalloc,
|
||||
devbufalign);
|
||||
}
|
||||
fhc->devbufstart = 0;
|
||||
fhc->devbufend = 0;
|
||||
fhc->lastblk_to_read (false);
|
||||
@ -112,7 +123,11 @@ fhandler_dev_raw::fixup_after_exec ()
|
||||
if (!close_on_exec ())
|
||||
{
|
||||
if (devbufsiz > 1L)
|
||||
devbuf = new char [devbufsiz];
|
||||
{
|
||||
/* Create sector-aligned buffer */
|
||||
devbufalloc = new char [devbufsiz + devbufalign];
|
||||
devbuf = (char *) roundup2 ((uintptr_t) devbufalloc, devbufalign);
|
||||
}
|
||||
devbufstart = 0;
|
||||
devbufend = 0;
|
||||
lastblk_to_read (false);
|
||||
@ -167,7 +182,7 @@ fhandler_dev_raw::ioctl (unsigned int cmd, void *buf)
|
||||
devbufend = 0;
|
||||
|
||||
if (devbufsiz > 1L)
|
||||
delete [] devbuf;
|
||||
delete [] devbufalloc;
|
||||
|
||||
devbufstart = 0;
|
||||
devbuf = buf;
|
||||
|
@ -1214,9 +1214,9 @@ fhandler_dev_tape::open (int flags, mode_t)
|
||||
if (!(flags & O_DIRECT))
|
||||
{
|
||||
devbufsiz = mt.drive (driveno ())->dp ()->MaximumBlockSize;
|
||||
devbuf = new char [devbufsiz];
|
||||
devbufalign = 1;
|
||||
devbufalloc = devbuf = new char [devbufsiz];
|
||||
}
|
||||
devbufstart = devbufend = 0;
|
||||
}
|
||||
else
|
||||
ReleaseMutex (mt_mtx);
|
||||
|
@ -1,6 +1,6 @@
|
||||
/* cygwin/fs.h
|
||||
|
||||
Copyright 2002, 2003 Red Hat Inc.
|
||||
Copyright 2002, 2003, 2012 Red Hat Inc.
|
||||
Written by Chris January <chris@atomice.net>
|
||||
|
||||
This file is part of Cygwin.
|
||||
@ -12,9 +12,13 @@ details. */
|
||||
#ifndef _CYGWIN_FS_H_
|
||||
#define _CYGWIN_FS_H_
|
||||
|
||||
#define BLKRRPART 0x0000125f
|
||||
#define BLKGETSIZE 0x00001260
|
||||
#define BLKSSZGET 0x00001268
|
||||
#define BLKRRPART 0x0000125f
|
||||
#define BLKGETSIZE 0x00001260
|
||||
#define BLKSSZGET 0x00001268
|
||||
#define BLKIOMIN 0x00001278
|
||||
#define BLKIOOPT 0x00001279
|
||||
#define BLKALIGNOFF 0x0000127a
|
||||
#define BLKPBSZGET 0x0000127b
|
||||
#define BLKGETSIZE64 0x00041268
|
||||
|
||||
#endif
|
||||
|
Loading…
x
Reference in New Issue
Block a user