Uses Windows API for reading/writing to improve error detection and reporting.

This commit is contained in:
Andrea Mazzoleni 2013-04-06 14:52:23 +02:00
parent aeb167bb16
commit e2c269fcdf
4 changed files with 227 additions and 20 deletions

View file

@ -3,6 +3,7 @@ SnapRAID HISTORY
3.1 2013/4
==========
* Diret use of Windows API for disk access to improve error reporting.
3.0 2013/3
==========

209
mingw.c
View file

@ -333,15 +333,6 @@ static void windows_info2stat(const BY_HANDLE_FILE_INFORMATION* info, const FILE
st->st_desc = "regular-dedup";
}
break;
/* All the other are skipped as reparse-point */
case IO_REPARSE_TAG_MOUNT_POINT :
st->st_mode = S_IFCHR;
st->st_desc = "reparse-point-mount";
break;
case IO_REPARSE_TAG_NFS :
st->st_mode = S_IFCHR;
st->st_desc = "reparse-point-nfs";
break;
case IO_REPARSE_TAG_SYMLINK :
if ((info->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0) {
st->st_mode = S_IFLNKDIR;
@ -351,6 +342,15 @@ static void windows_info2stat(const BY_HANDLE_FILE_INFORMATION* info, const FILE
st->st_desc = "reparse-point-symlink-file";
}
break;
/* All the other are skipped as reparse-point */
case IO_REPARSE_TAG_MOUNT_POINT :
st->st_mode = S_IFCHR;
st->st_desc = "reparse-point-mount";
break;
case IO_REPARSE_TAG_NFS :
st->st_mode = S_IFCHR;
st->st_desc = "reparse-point-nfs";
break;
default:
st->st_mode = S_IFCHR;
st->st_desc = "reparse-point";
@ -426,15 +426,6 @@ static void windows_finddata2stat(const WIN32_FIND_DATAW* info, struct windows_s
st->st_desc = "regular-dedup";
}
break;
/* All the other are skipped as reparse-point */
case IO_REPARSE_TAG_MOUNT_POINT :
st->st_mode = S_IFCHR;
st->st_desc = "reparse-point-mount";
break;
case IO_REPARSE_TAG_NFS :
st->st_mode = S_IFCHR;
st->st_desc = "reparse-point-nfs";
break;
case IO_REPARSE_TAG_SYMLINK :
if ((info->dwFileAttributes & FILE_ATTRIBUTE_DIRECTORY) != 0) {
st->st_mode = S_IFLNKDIR;
@ -444,6 +435,15 @@ static void windows_finddata2stat(const WIN32_FIND_DATAW* info, struct windows_s
st->st_desc = "reparse-point-symlink-file";
}
break;
/* All the other are skipped as reparse-point */
case IO_REPARSE_TAG_MOUNT_POINT :
st->st_mode = S_IFCHR;
st->st_desc = "reparse-point-mount";
break;
case IO_REPARSE_TAG_NFS :
st->st_mode = S_IFCHR;
st->st_desc = "reparse-point-nfs";
break;
default:
st->st_mode = S_IFCHR;
st->st_desc = "reparse-point";
@ -1069,5 +1069,178 @@ const char* windows_strerror(int err)
return last_error;
}
ssize_t windows_read(int fd, void* buffer, size_t size)
{
HANDLE h;
DWORD count;
if (fd == -1) {
errno = EBADF;
return -1;
}
h = (HANDLE)_get_osfhandle(fd);
if (h == INVALID_HANDLE_VALUE) {
errno = EBADF;
return -1;
}
if (!ReadFile(h, buffer, size, &count, 0)) {
windows_errno(GetLastError());
return -1;
}
return count;
}
ssize_t windows_write(int fd, const void* buffer, size_t size)
{
HANDLE h;
DWORD count;
if (fd == -1) {
errno = EBADF;
return -1;
}
h = (HANDLE)_get_osfhandle(fd);
if (h == INVALID_HANDLE_VALUE) {
errno = EBADF;
return -1;
}
if (!WriteFile(h, buffer, size, &count, 0)) {
windows_errno(GetLastError());
return -1;
}
return count;
}
off_t windows_lseek(int fd, off_t offset, int whence)
{
HANDLE h;
LARGE_INTEGER pos;
LARGE_INTEGER ret;
if (fd == -1) {
errno = EBADF;
return -1;
}
/* we support only SEEK_SET */
if (whence != SEEK_SET) {
errno = EINVAL;
return -1;
}
h = (HANDLE)_get_osfhandle(fd);
if (h == INVALID_HANDLE_VALUE) {
errno = EBADF;
return -1;
}
pos.QuadPart = offset;
if (!SetFilePointerEx(h, pos, &ret, FILE_BEGIN)) {
windows_errno(GetLastError());
return -1;
}
return ret.QuadPart;
}
ssize_t windows_pread(int fd, void* buffer, size_t size, off_t offset)
{
HANDLE h;
LARGE_INTEGER pos;
DWORD count;
if (fd == -1) {
errno = EBADF;
return -1;
}
h = (HANDLE)_get_osfhandle(fd);
if (h == INVALID_HANDLE_VALUE) {
errno = EBADF;
return -1;
}
retry:
pos.QuadPart = offset;
if (!SetFilePointerEx(h, pos, 0, FILE_BEGIN)) {
windows_errno(GetLastError());
return -1;
}
if (!ReadFile(h, buffer, size, &count, 0)) {
DWORD err = GetLastError();
/*
* If Windows is not able to allocate memory pages for the disk cache
* it could return the ERROR_NO_SYSTEM_RESOURCES error.
* In this case, the only possibility is to retry after a wait of few milliseconds.
*
* See:
* SQL Server reports operating system error 1450 or 1452 or 665 (retries)
* http://blogs.msdn.com/b/psssql/archive/2008/07/10/sql-server-reports-operating-system-error-1450-or-1452-or-665-retries.aspx
*
* 03-12-09 - ERROR_NO_SYSTEM_RESOURCES
* http://cbloomrants.blogspot.it/2009/03/03-12-09-errornosystemresources.html
*
* SnapRAID Help Forum: Error reading file
* https://sourceforge.net/projects/snapraid/forums/forum/1677233/topic/7273746
*/
if (err == ERROR_NO_SYSTEM_RESOURCES) {
fprintf(stderr, "Unexpected Windows ERROR_NO_SYSTEM_RESOURCES in pread(), retrying...\n");
Sleep(50);
goto retry;
}
windows_errno(err);
return -1;
}
return count;
}
ssize_t windows_pwrite(int fd, const void* buffer, size_t size, off_t offset)
{
HANDLE h;
LARGE_INTEGER pos;
DWORD count;
if (fd == -1) {
errno = EBADF;
return -1;
}
h = (HANDLE)_get_osfhandle(fd);
if (h == INVALID_HANDLE_VALUE) {
errno = EBADF;
return -1;
}
retry:
pos.QuadPart = offset;
if (!SetFilePointerEx(h, pos, 0, FILE_BEGIN)) {
windows_errno(GetLastError());
return -1;
}
if (!WriteFile(h, buffer, size, &count, 0)) {
DWORD err = GetLastError();
if (err == ERROR_NO_SYSTEM_RESOURCES) {
fprintf(stderr, "Unexpected Windows ERROR_NO_SYSTEM_RESOURCES in pwrite(), retrying...\n");
Sleep(50);
goto retry;
}
windows_errno(err);
return -1;
}
return count;
}
#endif

35
mingw.h
View file

@ -35,7 +35,6 @@
#define stat windows_stat
#define lstat windows_lstat
#define off_t off64_t
#define lseek lseek64
#define fstat windows_fstat
#define HAVE_FTRUNCATE 1
#define ftruncate windows_ftruncate
@ -63,12 +62,19 @@
#define S_ISLNK(m) (((m) & _S_IFMT) == S_IFLNK)
#define S_IFLNKDIR 0x6000 /* Symbolic link to directory */
#define S_ISLNKDIR(m) (((m) & _S_IFMT) == S_IFLNKDIR)
#define S_IFJUN 0x6000 /* Junction */
#define S_IFJUN 0x7000 /* Junction */
#define S_ISJUN(m) (((m) & _S_IFMT) == S_IFJUN)
#define readlink windows_readlink
#define symlink windows_symlink
#define link windows_link
#define strerror windows_strerror
#define read windows_read
#define write windows_write
#define lseek windows_lseek
#define HAVE_PREAD 1
#define HAVE_PWRITE 1
#define pread windows_pread
#define pwrite windows_pwrite
/* We have nano second support */
#define STAT_NSEC(st) (st)->st_mtimensec
@ -256,6 +262,31 @@ int windows_link(const char* existing, const char* file);
*/
const char* windows_strerror(int err);
/**
* Like read().
*/
ssize_t windows_read(int f, void* buffer, size_t size);
/**
* Like write().
*/
ssize_t windows_write(int f, const void* buffer, size_t size);
/**
* Like lseek().
*/
off_t windows_lseek(int f, off_t offset, int whence);
/**
* Like pread().
*/
ssize_t windows_pread(int f, void* buffer, size_t size, off_t offset);
/**
* Like pwrite().
*/
ssize_t windows_pwrite(int f, const void* buffer, size_t size, off_t offset);
#endif
#endif

2
util.c
View file

@ -49,7 +49,9 @@ static unsigned strdecset[256] =
STREAM* sopen_read(const char* file)
{
#if HAVE_POSIX_FADVISE
int ret;
#endif
STREAM* s = malloc_nofail(sizeof(STREAM));
s->handle_size = 1;