diff --git a/HISTORY b/HISTORY index ceb6daf0..4c4060ca 100644 --- a/HISTORY +++ b/HISTORY @@ -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 ========== diff --git a/mingw.c b/mingw.c index 988fed82..23b973f4 100644 --- a/mingw.c +++ b/mingw.c @@ -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 diff --git a/mingw.h b/mingw.h index 3726d11c..e3bdfeec 100644 --- a/mingw.h +++ b/mingw.h @@ -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 diff --git a/util.c b/util.c index 4c05bec9..a7f9fe81 100644 --- a/util.c +++ b/util.c @@ -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;