diff --git a/.gitignore b/.gitignore
index bb01378c..6579e59f 100644
--- a/.gitignore
+++ b/.gitignore
@@ -246,4 +246,3 @@ ModelManifest.xml
.fake/
*.am
-
diff --git a/ZFSin.sln b/ZFSin.sln
index 6258646e..ef1101e8 100644
--- a/ZFSin.sln
+++ b/ZFSin.sln
@@ -1,7 +1,7 @@
Microsoft Visual Studio Solution File, Format Version 12.00
-# Visual Studio 15
-VisualStudioVersion = 15.0.27004.2005
+# Visual Studio Version 16
+VisualStudioVersion = 16.0.30204.135
MinimumVisualStudioVersion = 10.0.40219.1
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "ZFSin", "ZFSin\ZFSin.vcxproj", "{9AFC9A86-1D07-49E1-9296-F7A3979B751D}"
EndProject
@@ -95,7 +95,6 @@ Global
{9AFC9A86-1D07-49E1-9296-F7A3979B751D}.Debug|ARM64.Deploy.0 = Debug|ARM64
{9AFC9A86-1D07-49E1-9296-F7A3979B751D}.Debug|x64.ActiveCfg = Debug|x64
{9AFC9A86-1D07-49E1-9296-F7A3979B751D}.Debug|x64.Build.0 = Debug|x64
- {9AFC9A86-1D07-49E1-9296-F7A3979B751D}.Debug|x64.Deploy.0 = Debug|x64
{9AFC9A86-1D07-49E1-9296-F7A3979B751D}.Debug|x86.ActiveCfg = Debug|Win32
{9AFC9A86-1D07-49E1-9296-F7A3979B751D}.Debug|x86.Build.0 = Debug|Win32
{9AFC9A86-1D07-49E1-9296-F7A3979B751D}.Debug|x86.Deploy.0 = Debug|Win32
diff --git a/ZFSin/ZFSin.vcxproj b/ZFSin/ZFSin.vcxproj
index 61fc6c6f..1b7939fa 100644
--- a/ZFSin/ZFSin.vcxproj
+++ b/ZFSin/ZFSin.vcxproj
@@ -458,6 +458,7 @@
+
@@ -643,6 +644,7 @@
+
@@ -699,4 +701,4 @@
-
\ No newline at end of file
+
diff --git a/ZFSin/zfs/cmd/zdb/zdb.c b/ZFSin/zfs/cmd/zdb/zdb.c
index 65e20b90..e3d63e9d 100644
--- a/ZFSin/zfs/cmd/zdb/zdb.c
+++ b/ZFSin/zfs/cmd/zdb/zdb.c
@@ -2463,7 +2463,7 @@ static void
dump_cachefile(const char *cachefile)
{
int fd;
- struct stat statbuf;
+ struct _stat64 statbuf;
char *buf;
nvlist_t *config;
@@ -2908,7 +2908,7 @@ dump_label(const char *dev)
int fd;
label_t labels[VDEV_LABELS];
char path[MAXPATHLEN];
- struct stat statbuf;
+ struct _stat64 statbuf;
uint64_t psize, ashift;
int l;
boolean_t label_found = B_FALSE;
diff --git a/ZFSin/zfs/cmd/zpool/zpool/runsdvui.cmd b/ZFSin/zfs/cmd/zpool/zpool/runsdvui.cmd
new file mode 100644
index 00000000..6f0c4b32
--- /dev/null
+++ b/ZFSin/zfs/cmd/zpool/zpool/runsdvui.cmd
@@ -0,0 +1,2 @@
+cd /d "C:\zfs\ZFSin\zfs\cmd\zpool\zpool" &msbuild "zpool.vcxproj" /t:sdvViewer /p:configuration="Debug" /p:platform="x64" /p:SolutionDir="C:\zfs"
+exit %errorlevel%
\ No newline at end of file
diff --git a/ZFSin/zfs/cmd/zpool/zpool_vdev.c b/ZFSin/zfs/cmd/zpool/zpool_vdev.c
index ecd612cf..82940d3a 100644
--- a/ZFSin/zfs/cmd/zpool/zpool_vdev.c
+++ b/ZFSin/zfs/cmd/zpool/zpool_vdev.c
@@ -1477,7 +1477,7 @@ make_disks(zpool_handle_t *zhp, nvlist_t *nv)
char vdev_path[MAX_PATH];
sprintf(vdev_path, "/dev/physicaldrive%lu", deviceNumber.DeviceNumber);
-
+
/*
* Update the path to refer to the partition. The presence of
* the 'whole_disk' field indicates to the CLI that we should
diff --git a/ZFSin/zfs/include/sys/fs/zfs.h b/ZFSin/zfs/include/sys/fs/zfs.h
index edbd3f41..4cc467e6 100644
--- a/ZFSin/zfs/include/sys/fs/zfs.h
+++ b/ZFSin/zfs/include/sys/fs/zfs.h
@@ -805,7 +805,7 @@ typedef struct zpool_load_policy {
* The location of the pool configuration repository, shared between kernel and
* userland.
*/
-#define ZPOOL_CACHE "/etc/zfs/zpool.cache"
+#define ZPOOL_CACHE "\\SystemRoot\\System32\\drivers\\zpool.cache"
/*
* vdev states are ordered from least to most healthy.
diff --git a/ZFSin/zfs/include/sys/spa.h b/ZFSin/zfs/include/sys/spa.h
index 7738112c..e12416aa 100644
--- a/ZFSin/zfs/include/sys/spa.h
+++ b/ZFSin/zfs/include/sys/spa.h
@@ -775,6 +775,12 @@ typedef enum {
SPA_AUTOTRIM_ON
} spa_autotrim_t;
+typedef enum spa_mode {
+ SPA_MODE_UNINIT = 0,
+ SPA_MODE_READ = 1,
+ SPA_MODE_WRITE = 2,
+} spa_mode_t;
+
/*
* Reason TRIM command was issued, used internally for accounting purposes.
*/
diff --git a/ZFSin/zfs/include/sys/vdev_file.h b/ZFSin/zfs/include/sys/vdev_file.h
index 7988cb41..2287053a 100644
--- a/ZFSin/zfs/include/sys/vdev_file.h
+++ b/ZFSin/zfs/include/sys/vdev_file.h
@@ -28,6 +28,7 @@
#define _SYS_VDEV_FILE_H
#include
+#include
#ifdef __cplusplus
extern "C" {
@@ -42,6 +43,11 @@ extern "C" {
} vdev_file_t;
#endif
+typedef struct vdev_file2 {
+ HANDLE vf_file;
+} vdev_file_t2;
+
+
#ifdef __cplusplus
}
#endif
diff --git a/ZFSin/zfs/include/sys/zfs_file.h b/ZFSin/zfs/include/sys/zfs_file.h
new file mode 100644
index 00000000..00546322
--- /dev/null
+++ b/ZFSin/zfs/include/sys/zfs_file.h
@@ -0,0 +1,58 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+#ifndef _SYS_ZFS_FILE_H
+#define _SYS_ZFS_FILE_H
+
+typedef HANDLE zfs_file_t;
+
+typedef struct zfs_file_attr {
+ ULONGLONG zfa_size;
+ DWORD zfa_type;
+} zfs_file_attr_t;
+
+int zfs_file_open(const char *path, int flags, int mode, zfs_file_t *fp);
+void zfs_file_close(zfs_file_t *fp);
+int zfs_file_write(zfs_file_t *fp, const void *buf, size_t len, ssize_t *resid);
+int zfs_file_getattr(zfs_file_t* fp, zfs_file_attr_t* zfattr);
+int zfs_file_read(zfs_file_t *fp, void *buf, size_t len, ssize_t *resid);
+int zfs_file_geomtery(zfs_file_t* hFile, zfs_file_attr_t* zattr);
+int zfs_file_pread(zfs_file_t* hFile, void* buf, DWORD dwBytesToRead, DWORD* resid, DWORD offset);
+//int zfs_file_pwrite(zfs_file_t *fp, const void *buf, size_t len, loff_t off,
+// ssize_t *resid);
+//int zfs_file_read(zfs_file_t *fp, void *buf, size_t len, ssize_t *resid);
+//int zfs_file_pread(zfs_file_t *fp, void *buf, size_t len, loff_t off,
+// ssize_t *resid);
+
+/*
+int zfs_file_seek(zfs_file_t *fp, loff_t *offp, int whence);
+int zfs_file_getattr(zfs_file_t *fp, zfs_file_attr_t *zfattr);
+int zfs_file_fsync(zfs_file_t *fp, int flags);
+int zfs_file_fallocate(zfs_file_t *fp, int mode, loff_t offset, loff_t len);
+loff_t zfs_file_off(zfs_file_t *fp);
+int zfs_file_unlink(const char *);
+
+int zfs_file_get(int fd, zfs_file_t **fp);
+void zfs_file_put(int fd);
+void *zfs_file_private(zfs_file_t *fp);
+*/
+
+#endif /* _SYS_ZFS_FILE_H */
diff --git a/ZFSin/zfs/lib/libspl/include/umem.h b/ZFSin/zfs/lib/libspl/include/umem.h
index 7c552213..681e5a5d 100644
--- a/ZFSin/zfs/lib/libspl/include/umem.h
+++ b/ZFSin/zfs/lib/libspl/include/umem.h
@@ -132,6 +132,12 @@ umem_free(void *ptr, size_t size)
free(ptr);
}
+static inline void
+umem_free_align(void* ptr, size_t size)
+{
+ _aligned_free(ptr);
+}
+
static inline void
umem_nofail_callback(umem_nofail_callback_t *cb) {}
@@ -189,8 +195,12 @@ umem_cache_free(umem_cache_t *cp, void *ptr)
{
if (cp->cache_destructor)
cp->cache_destructor(ptr, cp->cache_private);
-
- umem_free(ptr, cp->cache_bufsize);
+ if (cp->cache_align != 0)
+ {
+ umem_free_align(ptr, cp->cache_bufsize);
+ }
+ else
+ umem_free(ptr, cp->cache_bufsize);
}
static inline void
diff --git a/ZFSin/zfs/lib/libspl/include/wosix.h b/ZFSin/zfs/lib/libspl/include/wosix.h
index 3832a74b..34e56cfe 100644
--- a/ZFSin/zfs/lib/libspl/include/wosix.h
+++ b/ZFSin/zfs/lib/libspl/include/wosix.h
@@ -96,8 +96,12 @@ extern FILE *wosix_fdopen(int fildes, const char *mode);
#define pwrite64 wosix_pwrite
#undef fstat
#define fstat wosix_fstat
+#undef _fstat64
+#define _fstat64 wosix_fstat
#undef fstat_blk
#define fstat_blk wosix_fstat_blk
+#undef stat
+#define stat wosix_stat
#undef fdatasync
#define fdatasync wosix_fdatasync
#undef ftruncate
@@ -109,4 +113,4 @@ extern FILE *wosix_fdopen(int fildes, const char *mode);
#undef pipe
#define pipe wosix_pipe
-#endif /* WOSIX_HEADER */
\ No newline at end of file
+#endif /* WOSIX_HEADER */
diff --git a/ZFSin/zfs/lib/libspl/posix.c b/ZFSin/zfs/lib/libspl/posix.c
index 2406826a..7bbcf002 100644
--- a/ZFSin/zfs/lib/libspl/posix.c
+++ b/ZFSin/zfs/lib/libspl/posix.c
@@ -1034,6 +1034,16 @@ int wosix_mkdir(const char *path, mode_t mode)
return _mkdir(path);
}
+int wosix_stat(char *path, struct _stat64 *st)
+{
+ int fd;
+
+ fd = open(path, O_RDONLY);
+ if (fd == -1)
+ return -1;
+ return wosix_fstat(fd, st);
+}
+
// Only fill in what we actually use in ZFS
// Mostly used to test for existance, st_mode, st_size
// also FIFO and BLK (fixme)
diff --git a/ZFSin/zfs/lib/libuuid/gen_uuid.c b/ZFSin/zfs/lib/libuuid/gen_uuid.c
index abd0f5fa..0c4a35c7 100644
--- a/ZFSin/zfs/lib/libuuid/gen_uuid.c
+++ b/ZFSin/zfs/lib/libuuid/gen_uuid.c
@@ -559,7 +559,7 @@ void uuid_generate_random(uuid_t out)
*/
static int have_random_source(void)
{
- struct stat s;
+ struct _stat64 s;
return (!stat("/dev/random", &s) || !stat("/dev/urandom", &s));
}
diff --git a/ZFSin/zfs/lib/libzpool/kernel.c b/ZFSin/zfs/lib/libzpool/kernel.c
index 6f2c84eb..9aa2bf2a 100644
--- a/ZFSin/zfs/lib/libzpool/kernel.c
+++ b/ZFSin/zfs/lib/libzpool/kernel.c
@@ -52,6 +52,8 @@
#include
#endif
#include
+#include
+#include
/*
* Emulation of kernel services in userland.
@@ -771,7 +773,7 @@ vn_open(char *path, int x1, int flags, int mode, vnode_t **vpp, int x2, int x3)
if (fd == -1)
return (errno);
- if (fstat_blk(fd, &st) == -1) {
+ if (fstat(fd, &st) == -1) {
err = errno;
close(fd);
return (err);
@@ -787,8 +789,247 @@ vn_open(char *path, int x1, int flags, int mode, vnode_t **vpp, int x2, int x3)
return (0);
}
+// create a new file if file not exist else open file on the basis of flags
+int zfs_file_open(const char *path, int flags, int mode, zfs_file_t *fpp)
+{
+ wchar_t buf[PATH_MAX];
+ UNICODE_STRING uniName;
+ DWORD desiredAccess = 0;
+ DWORD dwCreationDisposition;
+ mbstowcs(buf, path, sizeof(buf));
+ if (flags == O_RDONLY)
+ {
+ desiredAccess = GENERIC_READ;
+ dwCreationDisposition = OPEN_EXISTING;
+ }
+
+ if (flags == O_WRONLY)
+ {
+ desiredAccess = GENERIC_READ | GENERIC_WRITE;
+ dwCreationDisposition = OPEN_ALWAYS | FILE_OVERWRITE_IF;
+ }
+
+ HANDLE hFile = CreateFileW(
+ buf,
+ desiredAccess,
+ FILE_SHARE_READ | FILE_SHARE_WRITE,
+ NULL,
+ OPEN_EXISTING,
+ FILE_ATTRIBUTE_NORMAL,
+ NULL
+ );
+ if (hFile == INVALID_HANDLE_VALUE) {
+ return E_FAIL;
+ }
+ *fpp = hFile;
+ return 0;
+}
+
+// read from a file and write to buf update next unread bytes
+int zfs_file_read(zfs_file_t* hFile, void* buf, DWORD dwBytesToRead, DWORD* resid)
+{
+ DWORD dwBytesRead;
+ HANDLE handle = hFile;
+ BOOL res = ReadFile(
+ *hFile,
+ buf,
+ dwBytesToRead,
+ &dwBytesRead,
+ NULL
+ );
+ if (!res)
+ {
+ return E_FAIL;
+ }
+ if (resid)
+ {
+ *resid = dwBytesToRead - dwBytesRead;
+ }
+ else if (dwBytesRead != dwBytesToRead)
+ {
+ return E_FAIL;
+ }
+ return 0;
+}
+
+int zfs_file_write(zfs_file_t* hFile, void* buf, DWORD dwBytesToWrite, DWORD* resid)
+{
+ DWORD dwBytesWritten;
+ BOOL res = WriteFile(
+ *hFile,
+ buf,
+ dwBytesToWrite,
+ &dwBytesWritten,
+ NULL
+ );
+ if (!res)
+ {
+ return E_FAIL;
+ }
+ if (resid)
+ {
+ *resid = dwBytesToWrite - dwBytesWritten;
+ }
+ else if (dwBytesToWrite != dwBytesWritten)
+ {
+ return E_FAIL;
+ }
+ return 0;
+}
+/*
+ Stateless read -> fp doesn't change with read operation
+ this func can be used only in case synchronous i/o
+*/
+int zfs_file_pread(zfs_file_t* hFile, void* buf, DWORD dwBytesToRead,DWORD* resid,DWORD offset)
+{
+ DWORD dwBytesRead;
+ OVERLAPPED ol = { .Offset = offset };
+ BOOL res = ReadFile(
+ *hFile,
+ buf,
+ dwBytesToRead,
+ &dwBytesRead,
+ &ol
+ );
+ if (!res)
+ {
+ return E_FAIL;
+ }
+ if (resid)
+ {
+ *resid = dwBytesToRead - dwBytesRead;
+ }
+ else if (dwBytesToRead != dwBytesRead)
+ {
+ return E_FAIL;
+ }
+ return 0;
+}
+
+/*
+ stateless write -> write at a given offset and os internal pointer is not updated
+*/
+int zfs_file_pwrite(zfs_file_t* hFile, const void* buf, DWORD dwBytesToWrite, DWORD* resid, DWORD offset)
+{
+ /*
+ * To simulate partial disk writes, we split writes into two
+ * system calls so that the process can be killed in between.
+ * This is used by ztest to simulate realistic failure modes.
+ */
+ int sectors,split;
+ sectors = dwBytesToWrite >> SPA_MINBLOCKSHIFT;
+ split = (sectors > 0 ? rand() % sectors : 0) << SPA_MINBLOCKSHIFT;
+ DWORD dwBytesWritten;
+ OVERLAPPED ol = { .Offset = offset };
+ BOOL res = WriteFile(
+ *hFile,
+ buf,
+ dwBytesToWrite,
+ &dwBytesWritten,
+ &ol
+ );
+ if (res)
+ {
+ OVERLAPPED ol2 = { .Offset = offset+split };
+ res = WriteFile(
+ *hFile,
+ (char*)buf+split,
+ dwBytesToWrite-split,
+ &dwBytesWritten,
+ &ol2
+ );
+ }
+ if (!res)
+ {
+ return E_FAIL;
+ }
+ if (resid)
+ {
+ *resid = dwBytesToWrite - dwBytesWritten;
+ }
+ else if (dwBytesToWrite != dwBytesWritten)
+ {
+ return E_FAIL;
+ }
+ return 0;
+}
+void zfs_file_close(zfs_file_t* hFile)
+{
+ CloseHandle(*hFile);
+}
/*ARGSUSED*/
+
+DWORD zfs_file_off(zfs_file_t* hFile) // 1
+{
+ PLONG lpDistanceToMoveHigh;
+ return SetFilePointer(
+ *hFile,
+ 0L,
+ &lpDistanceToMoveHigh, // this pointer is used for higher order 32 bits of the signed 64 bit distance to move, if set to NULL this won't be used
+ FILE_CURRENT
+ );
+}
+
+DWORD zfs_file_seek(zfs_file_t* hFile, LONG offset, DWORD dwMoveMethod)
+{
+ PLONG lpDistanceToMoveHigh;
+ return SetFilePointer(
+ *hFile,
+ offset,
+ &lpDistanceToMoveHigh, // this pointer is used for higher order 32 bits of the signed 64 bit distance to move
+ dwMoveMethod // FILE_BEGIN FILE_CURRENT FILE_END
+ );
+}
+
+BOOL zfs_file_flush(zfs_file_t* hFile,int flags)
+{
+ return FlushFileBuffers(
+ *hFile
+ );
+}
+
+int zfs_file_getattr(zfs_file_t *hFile, zfs_file_attr_t *zfattr)
+{
+ DWORD dwFileSize;
+ DWORD dwFileType;
+ LARGE_INTEGER fSize;
+ if (GetFileSizeEx(*hFile, &fSize))
+ {
+ zfattr->zfa_size = fSize.QuadPart;
+ }
+ DWORD err = GetLastError();
+ dwFileType = GetFileType(*hFile);
+ zfattr->zfa_type = dwFileType;
+ return 0;
+}
+
+int zfs_file_geomtery(zfs_file_t* hFile, zfs_file_attr_t* zattr)
+{
+ BOOL bResult = FALSE;
+ DWORD junk = 0;
+ DISK_GEOMETRY pdg = { 0 };
+ bResult = DeviceIoControl(
+ *hFile,
+ IOCTL_DISK_GET_DRIVE_GEOMETRY,
+ NULL,
+ 0,
+ &pdg,
+ sizeof(pdg),
+ &junk,
+ (LPOVERLAPPED)NULL
+ );
+ if (bResult)
+ {
+ ULONGLONG DiskSize = (ULONGLONG)pdg.Cylinders.QuadPart * (ULONGLONG)pdg.TracksPerCylinder *
+ (ULONGLONG)pdg.SectorsPerTrack * (ULONGLONG)pdg.BytesPerSector;
+ zattr->zfa_size = DiskSize;
+ zattr->zfa_type = GetFileType(*hFile);
+ return 0;
+ }
+ return GetLastError();
+}
+
int
vn_openat(char *path, int x1, int flags, int mode, vnode_t **vpp, int x2,
int x3, vnode_t *startvp/*, int fd*/)
@@ -797,7 +1038,7 @@ vn_openat(char *path, int x1, int flags, int mode, vnode_t **vpp, int x2,
int ret;
ASSERT(startvp == rootdir);
- (void) sprintf(realpath, "/%s", path);
+ (void) sprintf(realpath, "%s", path);
/* fd ignored for now, need if want to simulate nbmand support */
ret = vn_open(realpath, x1, flags, mode, vpp, x2, x3);
diff --git a/ZFSin/zfs/module/zfs/abd.c b/ZFSin/zfs/module/zfs/abd.c
index 8c426c5b..a1fb2280 100644
--- a/ZFSin/zfs/module/zfs/abd.c
+++ b/ZFSin/zfs/module/zfs/abd.c
@@ -866,7 +866,7 @@ abd_return_buf(abd_t *abd, void *buf, size_t n)
mutex_exit(&abd->abd_mutex);
ASSERT0(abd_cmp_buf(abd, buf, n));
mutex_enter(&abd->abd_mutex);
- zio_buf_free(buf, n);
+ zio_buf_free(buf, n); // not able to free the buffer
}
(void) zfs_refcount_remove_many(&abd->abd_children, n, buf);
diff --git a/ZFSin/zfs/module/zfs/spa.c b/ZFSin/zfs/module/zfs/spa.c
index 8c44fa2a..3051b956 100644
--- a/ZFSin/zfs/module/zfs/spa.c
+++ b/ZFSin/zfs/module/zfs/spa.c
@@ -2922,7 +2922,7 @@ spa_ld_select_uberblock(spa_t *spa, spa_import_type_t type)
/*
* Find the best uberblock.
*/
- vdev_uberblock_load(rvd, ub, &label);
+ vdev_uberblock_load(rvd, ub, &label); // failing here couldn't find any uberblock
/*
* If we weren't able to find a single valid uberblock, return failure.
diff --git a/ZFSin/zfs/module/zfs/spa_config.c b/ZFSin/zfs/module/zfs/spa_config.c
index 26e47c1c..0c0ddd2f 100644
--- a/ZFSin/zfs/module/zfs/spa_config.c
+++ b/ZFSin/zfs/module/zfs/spa_config.c
@@ -36,6 +36,7 @@
#include
#include
#include
+#include
#ifdef _KERNEL
#include
#include
@@ -86,6 +87,9 @@ spa_config_load(void)
char *pathname;
struct _buf *file;
uint64_t fsize;
+ zfs_file_t fp;
+ zfs_file_attr_t zfa;
+ int err;
#ifdef _KERNEL
if (zfs_autoimport_disable)
@@ -100,22 +104,23 @@ spa_config_load(void)
(void) snprintf(pathname, MAXPATHLEN, "%s%s",
"", spa_config_path);
- file = kobj_open_file(pathname);
+ err = zfs_file_open("C:\\WINDOWS\\System32\\drivers\\zpool.cache", O_RDONLY, 0, &fp);
kmem_free(pathname, MAXPATHLEN);
- if (file == (struct _buf *)-1)
+ if (err)
return;
- if (kobj_get_filesize(file, &fsize) != 0)
+ if (zfs_file_getattr(&fp, &zfa))
goto out;
+ fsize = zfa.zfa_size;
buf = kmem_alloc(fsize, KM_SLEEP);
/*
* Read the nvlist from the file.
*/
- if (kobj_read_file(file, buf, fsize, 0) < 0)
+ if (zfs_file_read(&fp, buf, fsize, NULL) < 0)
goto out;
/*
@@ -147,8 +152,7 @@ spa_config_load(void)
out:
if (buf != NULL)
kmem_free(buf, fsize);
-
- kobj_close_file(file);
+ zfs_file_close(&fp);
}
static void
@@ -158,10 +162,9 @@ spa_config_write(spa_config_dirent_t *dp, nvlist_t *nvl)
char *buf;
vnode_t *vp;
int oflags = FWRITE | FTRUNC | FCREAT | FOFFMAX;
-#ifdef __linux__
- int error;
-#endif
+ int err;
char *temp;
+ zfs_file_t fp;
/*
* If the nvlist is empty (NULL), then remove the old cachefile.
@@ -179,15 +182,32 @@ spa_config_write(spa_config_dirent_t *dp, nvlist_t *nvl)
* Pack the configuration into a buffer.
*/
buf = fnvlist_pack(nvl, &buflen);
- temp = kmem_zalloc(MAXPATHLEN, KM_SLEEP);
+ //temp = kmem_zalloc(MAXPATHLEN, KM_SLEEP);
/*
* Write the configuration to disk. We need to do the traditional
* 'write to temporary file, sync, move over original' to make sure we
* always have a consistent view of the data.
*/
- (void) snprintf(temp, MAXPATHLEN, "%s.tmp", dp->scd_path);
+ //(void) snprintf(temp, MAXPATHLEN, "%s.tmp", dp->scd_path);
+
+#ifdef _KERNEL
+ err = zfs_file_open(dp->scd_path, oflags, 0644, &fp);
+ if (err == 0) {
+ err = zfs_file_write(&fp, buf, buflen, NULL);
+ zfs_file_close(&fp);
+ }
+#if 0
+ if (err == 0)
+ err = zfs_file_fsync(fp, O_SYNC);
+
+ zfs_file_close(fp);
+ if (err)
+ (void) spa_config_remove(dp);
+#endif
+#endif
+#if 0
if (vn_open(temp, UIO_SYSSPACE, oflags, 0644, &vp, CRCREAT, 0) == 0) {
if (vn_rdwr(UIO_WRITE, vp, buf, buflen, 0, UIO_SYSSPACE,
0, RLIM64_INFINITY, kcred, NULL) == 0 &&
@@ -208,9 +228,9 @@ spa_config_write(spa_config_dirent_t *dp, nvlist_t *nvl)
#else
(void) vn_remove(temp, UIO_SYSSPACE, RMFILE);
#endif
-
+#endif
fnvlist_pack_free(buf, buflen);
- kmem_free(temp, MAXPATHLEN);
+ //kmem_free(temp, MAXPATHLEN);
}
/*
diff --git a/ZFSin/zfs/module/zfs/vdev.c b/ZFSin/zfs/module/zfs/vdev.c
index 688b433d..229fe39c 100644
--- a/ZFSin/zfs/module/zfs/vdev.c
+++ b/ZFSin/zfs/module/zfs/vdev.c
@@ -894,7 +894,7 @@ vdev_free(vdev_t *vd)
vdev_cache_fini(vd);
if (vd->vdev_path)
- spa_strfree(vd->vdev_path);
+ //spa_strfree(vd->vdev_path);
if (vd->vdev_devid)
spa_strfree(vd->vdev_devid);
if (vd->vdev_physpath)
@@ -1581,8 +1581,7 @@ vdev_set_deflate_ratio(vdev_t *vd)
/*
* Prepare a virtual device for access.
*/
-int
-vdev_open(vdev_t *vd)
+int vdev_open(vdev_t *vd)
{
spa_t *spa = vd->vdev_spa;
int error;
@@ -1712,11 +1711,11 @@ vdev_open(vdev_t *vd)
/*
* Make sure the allocatable size hasn't shrunk too much.
*/
- if (asize < vd->vdev_min_asize) {
- vdev_set_state(vd, B_TRUE, VDEV_STATE_CANT_OPEN,
- VDEV_AUX_BAD_LABEL);
- return (SET_ERROR(EINVAL));
- }
+ //if (asize < vd->vdev_min_asize) {
+ // vdev_set_state(vd, B_TRUE, VDEV_STATE_CANT_OPEN,
+ // VDEV_AUX_BAD_LABEL);
+ // return (SET_ERROR(EINVAL));
+ //}
if (vd->vdev_asize == 0) {
/*
@@ -1840,7 +1839,7 @@ vdev_validate(vdev_t *vd)
* any further validation. Otherwise, label I/O will fail and we will
* overwrite the previous state.
*/
- if (!vd->vdev_ops->vdev_op_leaf || !vdev_readable(vd))
+ if (!vd->vdev_ops->vdev_op_leaf || !vdev_readable(vd)) // vdev is readable therefore returned true
return (0);
/*
diff --git a/ZFSin/zfs/module/zfs/vdev_file.c b/ZFSin/zfs/module/zfs/vdev_file.c
index a7bcb07e..2f53dcd2 100644
--- a/ZFSin/zfs/module/zfs/vdev_file.c
+++ b/ZFSin/zfs/module/zfs/vdev_file.c
@@ -33,6 +33,7 @@
#include
#include
#include
+#include
/*
* Virtual device vector for files.
@@ -58,18 +59,276 @@ vdev_file_rele(vdev_t *vd)
extern int VOP_GETATTR(struct vnode *vp, vattr_t *vap, int flags, void *x3, void *x4);
#endif
+//static int
+//vdev_file_open(vdev_t *vd, uint64_t *psize, uint64_t *max_psize,
+// uint64_t *ashift)
+//{
+//#if _KERNEL
+// static vattr_t vattr;
+// vdev_file_t *vf;
+//#endif
+// int error = 0;
+//
+// dprintf("vdev_file_open %p\n", vd->vdev_tsd);
+// /* Rotational optimizations only make sense on block devices */
+// vd->vdev_nonrot = B_TRUE;
+//
+// /*
+// * Allow TRIM on file based vdevs. This may not always be supported,
+// * since it depends on your kernel version and underlying filesystem
+// * type but it is always safe to attempt.
+// */
+// vd->vdev_has_trim = B_TRUE;
+//
+// /*
+// * Disable secure TRIM on file based vdevs. There is no way to
+// * request this behavior from the underlying filesystem.
+// */
+// vd->vdev_has_securetrim = B_FALSE;
+//
+// /*
+// * We must have a pathname, and it must be absolute.
+// */
+// if (vd->vdev_path == NULL || (vd->vdev_path[0] != '/' &&
+// vd->vdev_path[0] != '\\')) {
+// vd->vdev_stat.vs_aux = VDEV_AUX_BAD_LABEL;
+// return (SET_ERROR(EINVAL));
+// }
+//
+// /*
+// * Reopen the device if it's not currently open. Otherwise,
+// * just update the physical size of the device.
+// */
+//#ifdef _KERNEL
+// if (vd->vdev_tsd != NULL) {
+// ASSERT(vd->vdev_reopening);
+// vf = vd->vdev_tsd;
+// goto skip_open;
+// }
+//
+// vf = vd->vdev_tsd = kmem_zalloc(sizeof (vdev_file_t), KM_SLEEP);
+//#endif
+//
+// /*
+// * We always open the files from the root of the global zone, even if
+// * we're in a local zone. If the user has gotten to this point, the
+// * administrator has already decided that the pool should be available
+// * to local zone users, so the underlying devices should be as well.
+// */
+// ASSERT(vd->vdev_path != NULL && (
+// vd->vdev_path[0] == '/' || vd->vdev_path[0] == '\\'));
+//
+// /*
+// vn_openat(char *pnamep,
+// enum uio_seg seg,
+// int filemode,
+// int createmode,
+// struct vnode **vpp,
+// enum create crwhy,
+// mode_t umask,
+// struct vnode *startvp)
+// extern int vn_openat(char *pnamep, enum uio_seg seg, int filemode,
+// int createmode, struct vnode **vpp, enum create crwhy,
+// mode_t umask, struct vnode *startvp);
+// */
+// uint8_t *FileName = NULL;
+// FileName = vd->vdev_path;
+//
+// if (!strncmp("\\\\?\\", FileName, 4)) {
+// FileName[1] = '?';
+// }
+//
+// dprintf("%s: opening '%s'\n", __func__, FileName);
+//
+//#ifdef _KERNEL
+//
+// ANSI_STRING AnsiFilespec;
+// UNICODE_STRING UnicodeFilespec;
+// OBJECT_ATTRIBUTES ObjectAttributes;
+//
+// SHORT UnicodeName[PATH_MAX];
+// CHAR AnsiName[PATH_MAX];
+// USHORT NameLength = 0;
+// NTSTATUS ntstatus;
+//
+// memset(UnicodeName, 0, sizeof(SHORT) * PATH_MAX);
+// memset(AnsiName, 0, sizeof(UCHAR) * PATH_MAX);
+//
+// NameLength = strlen(FileName);
+// ASSERT(NameLength < PATH_MAX);
+//
+// memmove(AnsiName, FileName, NameLength);
+//
+// AnsiFilespec.MaximumLength = AnsiFilespec.Length = NameLength;
+// AnsiFilespec.Buffer = AnsiName;
+//
+// UnicodeFilespec.MaximumLength = PATH_MAX * 2;
+// UnicodeFilespec.Length = 0;
+// UnicodeFilespec.Buffer = (PWSTR)UnicodeName;
+//
+// RtlAnsiStringToUnicodeString(&UnicodeFilespec, &AnsiFilespec, FALSE);
+//
+// ObjectAttributes.Length = sizeof(OBJECT_ATTRIBUTES);
+// ObjectAttributes.RootDirectory = NULL;
+// ObjectAttributes.Attributes = /*OBJ_CASE_INSENSITIVE |*/ OBJ_KERNEL_HANDLE;
+// ObjectAttributes.ObjectName = &UnicodeFilespec;
+// ObjectAttributes.SecurityDescriptor = NULL;
+// ObjectAttributes.SecurityQualityOfService = NULL;
+// IO_STATUS_BLOCK iostatus;
+//
+// ntstatus = ZwCreateFile(&vf->vf_handle,
+// spa_mode(vd->vdev_spa) == FREAD ? GENERIC_READ | SYNCHRONIZE : GENERIC_READ | GENERIC_WRITE | SYNCHRONIZE,
+// &ObjectAttributes,
+// &iostatus,
+// 0,
+// FILE_ATTRIBUTE_NORMAL,
+// /* FILE_SHARE_WRITE | */ FILE_SHARE_READ,
+// FILE_OPEN,
+// FILE_SYNCHRONOUS_IO_NONALERT | (spa_mode(vd->vdev_spa) == FREAD ? 0 : FILE_NO_INTERMEDIATE_BUFFERING),
+// NULL,
+// 0);
+//
+// if (ntstatus == STATUS_SUCCESS) {
+// error = 0;
+// } else {
+// vd->vdev_stat.vs_aux = VDEV_AUX_OPEN_FAILED;
+// goto failed;
+// }
+//
+//
+// /*
+// * Make sure it's a regular file.
+// */
+// FILE_STANDARD_INFORMATION info;
+// IO_STATUS_BLOCK iob;
+//
+// if ((ZwQueryInformationFile(
+// vf->vf_handle,
+// &iob,
+// &info,
+// sizeof(info),
+// FileStandardInformation) != STATUS_SUCCESS) ||
+// (info.Directory != FALSE)) {
+// vd->vdev_stat.vs_aux = VDEV_AUX_OPEN_FAILED;
+// ZwClose(vf->vf_handle);
+// error = ENOENT;
+// goto failed;
+// }
+//
+// // Since we will use DeviceObject and FileObject to do ioctl and IO
+// // we grab them now and lock them in place.
+// // Convert HANDLE to FileObject
+// PFILE_OBJECT FileObject;
+// PDEVICE_OBJECT DeviceObject;
+// NTSTATUS status;
+//
+// // This adds a reference to FileObject
+// status = ObReferenceObjectByHandle(
+// vf->vf_handle,
+// 0,
+// *IoFileObjectType,
+// KernelMode,
+// &FileObject,
+// NULL
+// );
+// if (status != STATUS_SUCCESS) {
+// ZwClose(vf->vf_handle);
+// vd->vdev_stat.vs_aux = VDEV_AUX_OPEN_FAILED;
+// error = EIO;
+// goto failed;
+// }
+//
+// // Convert FileObject to DeviceObject
+// DeviceObject = IoGetRelatedDeviceObject(FileObject);
+//
+// // Grab a reference to DeviceObject
+// ObReferenceObject(DeviceObject);
+//
+// vf->vf_FileObject = FileObject;
+// vf->vf_DeviceObject = DeviceObject;
+//
+// // Change it to SPARSE, so TRIM might work
+// status = ZwFsControlFile(
+// vf->vf_handle,
+// NULL,
+// NULL,
+// NULL,
+// NULL,
+// FSCTL_SET_SPARSE,
+// NULL,
+// 0,
+// NULL,
+// 0
+// );
+// dprintf("%s: set Sparse 0x%x.\n", __func__, status);
+//
+//#endif
+//
+//#if _KERNEL
+//skip_open:
+// /*
+// * Determine the physical size of the file.
+// */
+// //vattr.va_mask = AT_SIZE;
+// //vn_lock(vf->vf_vnode, LK_SHARED | LK_RETRY);
+// //error = VOP_GETATTR(vf->vf_vnode, &vattr, 0, kcred, NULL);
+// //VN_UNLOCK(vf->vf_vnode);
+//#endif
+//
+//#ifdef _KERNEL
+// *max_psize = *psize = info.EndOfFile.QuadPart;
+//#else
+// /* userland's vn_open() will get the device size for us, so we can
+// * just look it up - there is argument for a userland VOP_GETATTR to make
+// * this function cleaner. */
+//// *max_psize = *psize = vp->v_size;
+//#endif
+// *ashift = SPA_MINBLOCKSHIFT;
+//
+// return (0);
+//
+//failed:
+//#ifdef _KERNEL
+// if (vf) {
+// if (vf->vf_handle != NULL) {
+// vf->vf_handle = NULL;
+// }
+//
+// kmem_free(vf, sizeof(vdev_file_t));
+// vd->vdev_tsd = NULL;
+// }
+//#endif
+// return error;
+//}
+
+static mode_t vdev_file_open_mode(spa_mode_t spa_mode)
+{
+ mode_t mode = 0;
+ // TODO :- Add flags
+ if ((spa_mode & SPA_MODE_READ) && (spa_mode & SPA_MODE_WRITE)) {
+ mode = O_RDWR;
+ }
+ else if (spa_mode & SPA_MODE_READ) {
+ mode = O_RDONLY;
+ }
+ else if (spa_mode & SPA_MODE_WRITE) {
+ mode = O_WRONLY;
+ }
+ return mode;
+}
+
static int
-vdev_file_open(vdev_t *vd, uint64_t *psize, uint64_t *max_psize,
- uint64_t *ashift)
+vdev_file_open(vdev_t* vd, uint64_t* psize, uint64_t* max_psize,
+ uint64_t* ashift)
{
-#if _KERNEL
- static vattr_t vattr;
- vdev_file_t *vf;
-#endif
- int error = 0;
+ vdev_file_t2* vf;
+ zfs_file_t fp;
+ zfs_file_attr_t zfa;
+ int err;
- dprintf("vdev_file_open %p\n", vd->vdev_tsd);
- /* Rotational optimizations only make sense on block devices */
+ /*
+ * Rotational optimizations only make sense on block devices.
+ */
vd->vdev_nonrot = B_TRUE;
/*
@@ -88,243 +347,97 @@ vdev_file_open(vdev_t *vd, uint64_t *psize, uint64_t *max_psize,
/*
* We must have a pathname, and it must be absolute.
*/
- if (vd->vdev_path == NULL || (vd->vdev_path[0] != '/' &&
- vd->vdev_path[0] != '\\')) {
+
+ if (vd->vdev_path == NULL || (vd->vdev_path[0] != '/' && vd->vdev_path[0] != '\\')) {
vd->vdev_stat.vs_aux = VDEV_AUX_BAD_LABEL;
return (SET_ERROR(EINVAL));
}
- /*
- * Reopen the device if it's not currently open. Otherwise,
- * just update the physical size of the device.
- */
-#ifdef _KERNEL
if (vd->vdev_tsd != NULL) {
ASSERT(vd->vdev_reopening);
vf = vd->vdev_tsd;
goto skip_open;
}
- vf = vd->vdev_tsd = kmem_zalloc(sizeof (vdev_file_t), KM_SLEEP);
-#endif
-
- /*
- * We always open the files from the root of the global zone, even if
- * we're in a local zone. If the user has gotten to this point, the
- * administrator has already decided that the pool should be available
- * to local zone users, so the underlying devices should be as well.
- */
+ vf = vd->vdev_tsd = kmem_zalloc(sizeof(vdev_file_t2), KM_SLEEP);
ASSERT(vd->vdev_path != NULL && (
vd->vdev_path[0] == '/' || vd->vdev_path[0] == '\\'));
- /*
- vn_openat(char *pnamep,
- enum uio_seg seg,
- int filemode,
- int createmode,
- struct vnode **vpp,
- enum create crwhy,
- mode_t umask,
- struct vnode *startvp)
- extern int vn_openat(char *pnamep, enum uio_seg seg, int filemode,
- int createmode, struct vnode **vpp, enum create crwhy,
- mode_t umask, struct vnode *startvp);
- */
- uint8_t *FileName = NULL;
- FileName = vd->vdev_path;
-
- if (!strncmp("\\\\?\\", FileName, 4)) {
- FileName[1] = '?';
- }
-
- dprintf("%s: opening '%s'\n", __func__, FileName);
-
-#ifdef _KERNEL
-
- ANSI_STRING AnsiFilespec;
- UNICODE_STRING UnicodeFilespec;
- OBJECT_ATTRIBUTES ObjectAttributes;
-
- SHORT UnicodeName[PATH_MAX];
- CHAR AnsiName[PATH_MAX];
- USHORT NameLength = 0;
- NTSTATUS ntstatus;
-
- memset(UnicodeName, 0, sizeof(SHORT) * PATH_MAX);
- memset(AnsiName, 0, sizeof(UCHAR) * PATH_MAX);
-
- NameLength = strlen(FileName);
- ASSERT(NameLength < PATH_MAX);
-
- memmove(AnsiName, FileName, NameLength);
-
- AnsiFilespec.MaximumLength = AnsiFilespec.Length = NameLength;
- AnsiFilespec.Buffer = AnsiName;
-
- UnicodeFilespec.MaximumLength = PATH_MAX * 2;
- UnicodeFilespec.Length = 0;
- UnicodeFilespec.Buffer = (PWSTR)UnicodeName;
-
- RtlAnsiStringToUnicodeString(&UnicodeFilespec, &AnsiFilespec, FALSE);
-
- ObjectAttributes.Length = sizeof(OBJECT_ATTRIBUTES);
- ObjectAttributes.RootDirectory = NULL;
- ObjectAttributes.Attributes = /*OBJ_CASE_INSENSITIVE |*/ OBJ_KERNEL_HANDLE;
- ObjectAttributes.ObjectName = &UnicodeFilespec;
- ObjectAttributes.SecurityDescriptor = NULL;
- ObjectAttributes.SecurityQualityOfService = NULL;
- IO_STATUS_BLOCK iostatus;
-
- ntstatus = ZwCreateFile(&vf->vf_handle,
- spa_mode(vd->vdev_spa) == FREAD ? GENERIC_READ | SYNCHRONIZE : GENERIC_READ | GENERIC_WRITE | SYNCHRONIZE,
- &ObjectAttributes,
- &iostatus,
- 0,
- FILE_ATTRIBUTE_NORMAL,
- /* FILE_SHARE_WRITE | */ FILE_SHARE_READ,
- FILE_OPEN,
- FILE_SYNCHRONOUS_IO_NONALERT | (spa_mode(vd->vdev_spa) == FREAD ? 0 : FILE_NO_INTERMEDIATE_BUFFERING),
- NULL,
- 0);
-
- if (ntstatus == STATUS_SUCCESS) {
- error = 0;
- } else {
- vd->vdev_stat.vs_aux = VDEV_AUX_OPEN_FAILED;
- goto failed;
- }
-
-
- /*
- * Make sure it's a regular file.
- */
- FILE_STANDARD_INFORMATION info;
- IO_STATUS_BLOCK iob;
-
- if ((ZwQueryInformationFile(
- vf->vf_handle,
- &iob,
- &info,
- sizeof(info),
- FileStandardInformation) != STATUS_SUCCESS) ||
- (info.Directory != FALSE)) {
+ vd->vdev_path = "\\\\.\\PhysicalDrive1";
+ err = zfs_file_open(vd->vdev_path, vdev_file_open_mode(spa_mode(vd->vdev_spa)), 0, &fp);
+ if (err) {
vd->vdev_stat.vs_aux = VDEV_AUX_OPEN_FAILED;
- ZwClose(vf->vf_handle);
- error = ENOENT;
- goto failed;
+ return (err);
}
-
- // Since we will use DeviceObject and FileObject to do ioctl and IO
- // we grab them now and lock them in place.
- // Convert HANDLE to FileObject
- PFILE_OBJECT FileObject;
- PDEVICE_OBJECT DeviceObject;
- NTSTATUS status;
-
- // This adds a reference to FileObject
- status = ObReferenceObjectByHandle(
- vf->vf_handle,
- 0,
- *IoFileObjectType,
- KernelMode,
- &FileObject,
- NULL
- );
- if (status != STATUS_SUCCESS) {
- ZwClose(vf->vf_handle);
+ vf->vf_file = fp;
+
+ //#ifdef _KERNEL
+ // /*
+ // * Make sure it's a regular file.
+ // */
+ // if (zfs_file_getattr(fp, &zfa)) {
+ // return (SET_ERROR(ENODEV));
+ // }
+ // if (!S_ISREG(zfa.zfa_mode)) {
+ // vd->vdev_stat.vs_aux = VDEV_AUX_OPEN_FAILED;
+ // return (SET_ERROR(ENODEV));
+ // }
+ //#endif
+skip_open:
+#ifdef _KERNEL
+ err = zfs_file_getattr(vf->vf_file, &zfa);
+ if (err) {
vd->vdev_stat.vs_aux = VDEV_AUX_OPEN_FAILED;
- error = EIO;
- goto failed;
+ return (err);
}
-
- // Convert FileObject to DeviceObject
- DeviceObject = IoGetRelatedDeviceObject(FileObject);
-
- // Grab a reference to DeviceObject
- ObReferenceObject(DeviceObject);
-
- vf->vf_FileObject = FileObject;
- vf->vf_DeviceObject = DeviceObject;
-
- // Change it to SPARSE, so TRIM might work
- status = ZwFsControlFile(
- vf->vf_handle,
- NULL,
- NULL,
- NULL,
- NULL,
- FSCTL_SET_SPARSE,
- NULL,
- 0,
- NULL,
- 0
- );
- dprintf("%s: set Sparse 0x%x.\n", __func__, status);
-
-#endif
-
-#if _KERNEL
-skip_open:
- /*
- * Determine the physical size of the file.
- */
- //vattr.va_mask = AT_SIZE;
- //vn_lock(vf->vf_vnode, LK_SHARED | LK_RETRY);
- //error = VOP_GETATTR(vf->vf_vnode, &vattr, 0, kcred, NULL);
- //VN_UNLOCK(vf->vf_vnode);
-#endif
-
-#ifdef _KERNEL
- *max_psize = *psize = info.EndOfFile.QuadPart;
#else
- /* userland's vn_open() will get the device size for us, so we can
- * just look it up - there is argument for a userland VOP_GETATTR to make
- * this function cleaner. */
-// *max_psize = *psize = vp->v_size;
+ err = zfs_file_geomtery(&fp, &zfa);
#endif
- *ashift = SPA_MINBLOCKSHIFT;
-
+ * max_psize = *psize = zfa.zfa_size;
+ *ashift = SPA_MINBLOCKSHIFT;
return (0);
-
-failed:
-#ifdef _KERNEL
- if (vf) {
- if (vf->vf_handle != NULL) {
- vf->vf_handle = NULL;
- }
-
- kmem_free(vf, sizeof(vdev_file_t));
- vd->vdev_tsd = NULL;
- }
-#endif
- return error;
}
-static void
-vdev_file_close(vdev_t *vd)
+//static void
+//vdev_file_close(vdev_t *vd)
+//{
+//#ifdef _KERNEL
+// vdev_file_t *vf = vd->vdev_tsd;
+//
+// if (vd->vdev_reopening || vf == NULL)
+// return;
+//
+// if (vf->vf_handle != NULL) {
+//
+// // Release our holds
+// ObDereferenceObject(vf->vf_FileObject);
+// ObDereferenceObject(vf->vf_DeviceObject);
+//
+// ZwClose(vf->vf_handle);
+// }
+//
+// vf->vf_FileObject = NULL;
+// vf->vf_DeviceObject = NULL;
+// vf->vf_handle = NULL;
+// vd->vdev_delayed_close = B_FALSE;
+// kmem_free(vf, sizeof (vdev_file_t));
+// vd->vdev_tsd = NULL;
+//#endif
+//}
+
+static void vdev_file_close(vdev_t* vd)
{
-#ifdef _KERNEL
- vdev_file_t *vf = vd->vdev_tsd;
+ vdev_file_t2* vf = vd->vdev_tsd;
if (vd->vdev_reopening || vf == NULL)
return;
- if (vf->vf_handle != NULL) {
-
- // Release our holds
- ObDereferenceObject(vf->vf_FileObject);
- ObDereferenceObject(vf->vf_DeviceObject);
-
- ZwClose(vf->vf_handle);
+ if (vf->vf_file != NULL) {
+ (void)zfs_file_close(&vf->vf_file);
}
-
- vf->vf_FileObject = NULL;
- vf->vf_DeviceObject = NULL;
- vf->vf_handle = NULL;
vd->vdev_delayed_close = B_FALSE;
- kmem_free(vf, sizeof (vdev_file_t));
+ kmem_free(vf, sizeof(vdev_file_t2));
vd->vdev_tsd = NULL;
-#endif
}
#ifdef _KERNEL
@@ -405,6 +518,7 @@ vdev_file_io_intrxxx(PDEVICE_OBJECT DeviceObject, PIRP irp, PVOID Context)
*/
_Atomic uint64_t zfs_vdev_file_size_mismatch_cnt = 0;
+// clear the changes
static void
vdev_file_io_start(zio_t *zio)
{
@@ -464,14 +578,17 @@ vdev_file_io_start(zio_t *zio)
ASSERT(zio->io_size != 0);
#ifdef _KERNEL
- vdev_file_t *vf = vd->vdev_tsd;
-
+ vdev_file_t* vf = vd->vdev_tsd;
+#else
+ vdev_file_t2* vf = vd->vdev_tsd;
+#endif // _KERNEL
+ LARGE_INTEGER offset;
+ offset.QuadPart = zio->io_offset + vd->vdev_win_offset;
+#ifdef _KERNEL
PIRP irp = NULL;
PIO_STACK_LOCATION irpStack = NULL;
IO_STATUS_BLOCK IoStatusBlock = { 0 };
- LARGE_INTEGER offset;
- offset.QuadPart = zio->io_offset + vd->vdev_win_offset;
/* Preallocate space for IoWorkItem, required for vdev_file_io_start_done callback */
vf_callback_t *vb = (vf_callback_t *)kmem_alloc(sizeof(vf_callback_t) + IoSizeofWorkItem(), KM_SLEEP);
@@ -534,6 +651,45 @@ vdev_file_io_start(zio_t *zio)
TRUE);// On Cancel
IoCallDriver(vf->vf_DeviceObject, irp);
+#else
+ void* data;
+ int err;
+ DWORD red;
+ HANDLE hFile = vf->vf_file;
+
+ if (!SetFilePointerEx(hFile, offset, NULL, FILE_BEGIN))
+ goto failed;
+
+ if (zio->io_type == ZIO_TYPE_READ) {
+ ASSERT3S(zio->io_abd->abd_size, >= , zio->io_size);
+ //data =
+ // abd_borrow_buf(zio->io_abd, zio->io_abd->abd_size);
+ //ok = ReadFile(hFile, data, zio->io_size, &red, NULL);
+ //abd_return_buf_copy(zio->io_abd, data, zio->io_size);
+ data = abd_borrow_buf(zio->io_abd, zio->io_abd->abd_size);
+ //err = ReadFile(hFile, data, zio->io_size, &red, NULL);
+ err = zfs_file_pread(&hFile, data, zio->io_size, &red, zio->io_offset);
+ abd_return_buf_copy(zio->io_abd, data, zio->io_size); // see in kernel space what is happening
+ }
+ else {
+ ASSERT3S(zio->io_abd->abd_size, >= , zio->io_size);
+ data =
+ abd_borrow_buf_copy(zio->io_abd, zio->io_abd->abd_size);
+ err = WriteFile(hFile, data, zio->io_size, &red, NULL);
+ abd_return_buf_off(zio->io_abd, data,
+ 0, zio->io_size, zio->io_abd->abd_size);
+ }
+
+failed:
+ if (err)
+ zio->io_error = EIO;
+ else if (red)
+ zio->io_error = SET_ERROR(ENOSPC);
+ else
+ zio->io_error = 0;
+
+ zio_delay_interrupt(zio);
+ return;
#endif
return;
diff --git a/ZFSin/zfs/module/zfs/zfs_file.c b/ZFSin/zfs/module/zfs/zfs_file.c
new file mode 100644
index 00000000..7248cb7a
--- /dev/null
+++ b/ZFSin/zfs/module/zfs/zfs_file.c
@@ -0,0 +1,576 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+
+#include
+#include
+#include
+#include
+//#include
+//#include
+//#include
+#ifdef HAVE_FDTABLE_HEADER
+#include
+#endif
+
+/*
+ * Open file
+ *
+ * path - fully qualified path to file
+ * flags - file attributes O_READ / O_WRITE / O_EXCL
+ * fpp - pointer to return file pointer
+ *
+ * Returns 0 on success underlying error on failure.
+ */
+int
+zfs_file_open(const char *path, int flags, int mode, zfs_file_t *fpp)
+{
+ vnode_t *vp;
+ wchar_t buf[PATH_MAX];
+ UNICODE_STRING uniName;
+ OBJECT_ATTRIBUTES objAttr;
+ HANDLE handle;
+ NTSTATUS ntstatus;
+ IO_STATUS_BLOCK ioStatusBlock;
+
+ mbstowcs(buf, path, sizeof (buf));
+ RtlInitUnicodeString(&uniName, buf);
+ InitializeObjectAttributes(&objAttr, &uniName,
+ OBJ_CASE_INSENSITIVE | OBJ_KERNEL_HANDLE,
+ NULL, NULL);
+
+ if(KeGetCurrentIrql() != PASSIVE_LEVEL)
+ return -1;
+
+ ntstatus = ZwCreateFile(&handle,
+ GENERIC_WRITE,
+ &objAttr, &ioStatusBlock, NULL,
+ FILE_ATTRIBUTE_NORMAL,
+ 0,
+ FILE_OVERWRITE_IF,
+ FILE_SYNCHRONOUS_IO_NONALERT,
+ NULL, 0);
+
+ if (ntstatus != STATUS_SUCCESS) {
+ return -1;
+ }
+
+ *fpp = handle;
+
+ return 0;
+#if 0
+ struct file *filp;
+ int saved_umask;
+
+ if (!(flags & O_CREAT) && (flags & O_WRONLY))
+ flags |= O_EXCL;
+
+ if (flags & O_CREAT)
+ saved_umask = xchg(¤t->fs->umask, 0);
+
+ filp = filp_open(path, flags, mode);
+
+ if (flags & O_CREAT)
+ (void) xchg(¤t->fs->umask, saved_umask);
+
+ if (IS_ERR(filp))
+ return (-PTR_ERR(filp));
+
+ *fpp = filp;
+ return (0);
+#endif
+}
+
+void
+zfs_file_close(zfs_file_t *fp)
+{
+ ZwClose(*fp);
+ //filp_close(fp, 0);
+}
+
+// need to implement read,write,pread,pwrite
+
+
+
+
+#if 0
+static ssize_t
+zfs_file_write_impl(zfs_file_t *fp, const void *buf, size_t count, loff_t *off)
+{
+#if defined(HAVE_KERNEL_WRITE_PPOS)
+ return (kernel_write(fp, buf, count, off));
+#else
+ mm_segment_t saved_fs;
+ ssize_t rc;
+
+ saved_fs = get_fs();
+ set_fs(KERNEL_DS);
+
+ rc = vfs_write(fp, (__force const char __user __user *)buf, count, off);
+
+ set_fs(saved_fs);
+
+ return (rc);
+#endif
+}
+#endif
+
+/*
+ * Stateful write - use os internal file pointer to determine where to
+ * write and update on successful completion.
+ *
+ * fp - pointer to file (pipe, socket, etc) to write to
+ * buf - buffer to write
+ * count - # of bytes to write
+ * resid - pointer to count of unwritten bytes (if short write)
+ *
+ * Returns 0 on success errno on failure.
+ */
+int
+zfs_file_write(zfs_file_t *fp, const void *buf, size_t count, ssize_t *resid)
+{
+ NTSTATUS ntstatus;
+ IO_STATUS_BLOCK ioStatusBlock;
+
+ ntstatus = ZwWriteFile(*fp, NULL, NULL, NULL,
+ &ioStatusBlock, buf, count, NULL, NULL);
+
+ if (resid)
+ *resid = 0;
+
+ if (STATUS_SUCCESS != ntstatus)
+ return (EIO);
+ return (0);
+#if 0
+ loff_t off = fp->f_pos;
+ ssize_t rc;
+
+ rc = zfs_file_write_impl(fp, buf, count, &off);
+ if (rc < 0)
+ return (-rc);
+
+ fp->f_pos = off;
+
+ if (resid) {
+ *resid = count - rc;
+ } else if (rc != count) {
+ return (EIO);
+ }
+#endif
+}
+
+
+
+
+
+/*
+ * Stateful read - use os internal file pointer to determine where to
+ * read and update on successful completion.
+ *
+ * fp - pointer to file (pipe, socket, etc) to read from
+ * buf - buffer to write
+ * count - # of bytes to read
+ * resid - pointer to count of unread bytes (if short read)
+ *
+ * Returns 0 on success errno on failure.
+ */
+int zfs_file_read(zfs_file_t* fp, const void* buf, size_t count, ssize_t* resid)
+{
+ NTSTATUS ntstatus;
+ IO_STATUS_BLOCK ioStatusBlock;
+ ntstatus = ZwReadFile(*fp, NULL, NULL, NULL, &ioStatusBlock, buf, count, NULL, NULL);
+ if (STATUS_SUCCESS != ntstatus)
+ return (EIO);
+ if (resid)
+ {
+ *resid = 0;
+ }
+ return (0);
+#if 0
+ loff_t off = fp->f_pos;
+ ssize_t rc;
+
+ rc = zfs_file_read_impl(fp, buf, count, &off);
+ if (rc < 0)
+ return (-rc);
+
+ fp->f_pos = off;
+
+ if (resid) {
+ *resid = count - rc;
+ }
+ else if (rc != count) {
+ return (EIO);
+ }
+
+ return (0);
+#endif
+}
+
+/*
+ * Stateless write - os internal file pointer is not updated.
+ *
+ * fp - pointer to file (pipe, socket, etc) to write to
+ * buf - buffer to write
+ * count - # of bytes to write
+ * off - file offset to write to (only valid for seekable types)
+ * resid - pointer to count of unwritten bytes
+ *
+ * Returns 0 on success errno on failure.
+ */
+int
+zfs_file_pwrite(zfs_file_t* fp, const void* buf, size_t count, loff_t off,
+ ssize_t* resid)
+{
+ NTSTATUS ntstatus;
+ IO_STATUS_BLOCK ioStatusBlock;
+ LARGE_INTEGER offset = { 0 };
+ offset.LowPart = off;
+ ntstatus = ZwReadFile(fp, NULL, NULL, NULL, &ioStatusBlock, buf, count, &offset, NULL);
+ // reset fp to its original position
+ if (STATUS_SUCCESS != ntstatus)
+ return (EIO);
+ if (resid)
+ {
+ *resid = 0;
+ }
+ return (0);
+#if 0
+ ssize_t rc;
+
+ rc = zfs_file_write_impl(fp, buf, count, &off);
+ if (rc < 0)
+ return (-rc);
+
+ if (resid) {
+ *resid = count - rc;
+ }
+ else if (rc != count) {
+ return (EIO);
+ }
+
+ return (0);
+#endif
+}
+
+/*
+ * Stateless read - os internal file pointer is not updated.
+ *
+ * fp - pointer to file (pipe, socket, etc) to read from
+ * buf - buffer to write
+ * count - # of bytes to write
+ * off - file offset to read from (only valid for seekable types)
+ * resid - pointer to count of unwritten bytes (if short write)
+ *
+ * Returns 0 on success errno on failure.
+ */
+int
+zfs_file_pread(zfs_file_t* fp, void* buf, DWORD count, DWORD* resid,
+ DWORD off)
+{
+ NTSTATUS ntstatus;
+ IO_STATUS_BLOCK ioStatusBlock;
+ LARGE_INTEGER offset = { 0 };
+ offset.LowPart = off;
+ /*FileInformationClass info;
+ ZwQueryInformationFile*/
+ ntstatus = ZwReadFile(fp, NULL, NULL, NULL, &ioStatusBlock, buf, count, &offset, NULL);
+ if (STATUS_SUCCESS != ntstatus)
+ return (EIO);
+ if (resid)
+ {
+ *resid = 0;
+ }
+ return (0);
+#if 0
+ ssize_t rc;
+
+ rc = zfs_file_read_impl(fp, buf, count, &off);
+ if (rc < 0)
+ return (-rc);
+
+ if (resid) {
+ *resid = count - rc;
+ }
+ else if (rc != count) {
+ return (EIO);
+ }
+
+ return (0);
+#endif
+}
+
+/*
+ * Sync file to disk
+ *
+ * filp - file pointer
+ * flags - O_SYNC and or O_DSYNC
+ *
+ * Returns 0 on success or error code of underlying sync call on failure.
+ */
+int
+zfs_file_fsync(zfs_file_t* filp, int flags)
+{
+ if (KeGetCurrentIrql() != PASSIVE_LEVEL)
+ return -1;
+ IO_STATUS_BLOCK ioStatusBlock;
+ NTSTATUS ntStatus;
+ ntStatus = ZwFlushBuffersFile(
+ *filp,
+ &ioStatusBlock
+ );
+ if (ntStatus != STATUS_SUCCESS) {
+ return -1;
+ }
+ return 0;
+#if 0
+ int datasync = 0;
+ int error;
+ int fstrans;
+
+ if (flags & O_DSYNC)
+ datasync = 1;
+
+ /*
+ * May enter XFS which generates a warning when PF_FSTRANS is set.
+ * To avoid this the flag is cleared over vfs_sync() and then reset.
+ */
+ fstrans = __spl_pf_fstrans_check();
+ if (fstrans)
+ current->flags &= ~(__SPL_PF_FSTRANS);
+
+ error = -vfs_fsync(filp, datasync);
+
+ if (fstrans)
+ current->flags |= __SPL_PF_FSTRANS;
+
+ return (error);
+#endif
+}
+
+/*
+ * Get file attributes
+ *
+ * filp - file pointer
+ * zfattr - pointer to file attr structure
+ *
+ * Currently only used for fetching size and file mode.
+ *
+ * Returns 0 on success or error code of underlying getattr call on failure.
+ */
+int
+zfs_file_getattr(zfs_file_t* filp, zfs_file_attr_t* zfattr)
+{
+ FILE_STANDARD_INFORMATION fileInfo = { 0 };
+ IO_STATUS_BLOCK ioStatusBlock;
+ NTSTATUS ntStatus;
+ ntStatus = ZwQueryInformationFile(
+ *filp,
+ &ioStatusBlock,
+ &fileInfo,
+ sizeof(fileInfo),
+ FileNameInformation
+ );
+ if (ntStatus != STATUS_SUCCESS) {
+ return -1;
+ }
+ zfattr->zfa_size = fileInfo.EndOfFile.QuadPart;
+#if 0
+ struct kstat stat;
+ int rc;
+
+#if defined(HAVE_4ARGS_VFS_GETATTR)
+ rc = vfs_getattr(&filp->f_path, &stat, STATX_BASIC_STATS,
+ AT_STATX_SYNC_AS_STAT);
+#elif defined(HAVE_2ARGS_VFS_GETATTR)
+ rc = vfs_getattr(&filp->f_path, &stat);
+#else
+ rc = vfs_getattr(filp->f_path.mnt, filp->f_dentry, &stat);
+#endif
+ if (rc)
+ return (-rc);
+
+ zfattr->zfa_size = stat.size;
+ zfattr->zfa_mode = stat.mode;
+
+ return (0);
+#endif
+}
+#if 0
+static ssize_t
+zfs_file_read_impl(zfs_file_t* fp, void* buf, size_t count, loff_t* off)
+{
+#if defined(HAVE_KERNEL_READ_PPOS)
+ return (kernel_read(fp, buf, count, off));
+#else
+ mm_segment_t saved_fs;
+ ssize_t rc;
+
+ saved_fs = get_fs();
+ set_fs(KERNEL_DS);
+
+ rc = vfs_read(fp, (void __user*)buf, count, off);
+ set_fs(saved_fs);
+
+ return (rc);
+#endif
+}
+
+/*
+ * lseek - set / get file pointer
+ *
+ * fp - pointer to file (pipe, socket, etc) to read from
+ * offp - value to seek to, returns current value plus passed offset
+ * whence - see man pages for standard lseek whence values
+ *
+ * Returns 0 on success errno on failure (ESPIPE for non seekable types)
+ */
+int
+zfs_file_seek(zfs_file_t *fp, loff_t *offp, int whence)
+{
+ loff_t rc;
+
+ if (*offp < 0 || *offp > MAXOFFSET_T)
+ return (EINVAL);
+
+ rc = vfs_llseek(fp, *offp, whence);
+ if (rc < 0)
+ return (-rc);
+
+ *offp = rc;
+
+ return (0);
+}
+
+/*
+ * fallocate - allocate or free space on disk
+ *
+ * fp - file pointer
+ * mode (non-standard options for hole punching etc)
+ * offset - offset to start allocating or freeing from
+ * len - length to free / allocate
+ *
+ * OPTIONAL
+ */
+int
+zfs_file_fallocate(zfs_file_t *fp, int mode, loff_t offset, loff_t len)
+{
+ /*
+ * May enter XFS which generates a warning when PF_FSTRANS is set.
+ * To avoid this the flag is cleared over vfs_sync() and then reset.
+ */
+ int fstrans = __spl_pf_fstrans_check();
+ if (fstrans)
+ current->flags &= ~(__SPL_PF_FSTRANS);
+
+ /*
+ * When supported by the underlying file system preferentially
+ * use the fallocate() callback to preallocate the space.
+ */
+ int error = EOPNOTSUPP;
+ if (fp->f_op->fallocate)
+ error = fp->f_op->fallocate(fp, mode, offset, len);
+
+ if (fstrans)
+ current->flags |= __SPL_PF_FSTRANS;
+
+ return (error);
+}
+
+/*
+ * Request current file pointer offset
+ *
+ * fp - pointer to file
+ *
+ * Returns current file offset.
+ */
+loff_t
+zfs_file_off(zfs_file_t *fp)
+{
+ return (fp->f_pos);
+}
+
+/*
+ * Request file pointer private data
+ *
+ * fp - pointer to file
+ *
+ * Returns pointer to file private data.
+ */
+void *
+zfs_file_private(zfs_file_t *fp)
+{
+ return (fp->private_data);
+}
+
+/*
+ * unlink file
+ *
+ * path - fully qualified file path
+ *
+ * Returns 0 on success.
+ *
+ * OPTIONAL
+ */
+int
+zfs_file_unlink(const char *path)
+{
+ return (EOPNOTSUPP);
+}
+
+/*
+ * Get reference to file pointer
+ *
+ * fd - input file descriptor
+ * fpp - pointer to file pointer
+ *
+ * Returns 0 on success EBADF on failure.
+ */
+int
+zfs_file_get(int fd, zfs_file_t **fpp)
+{
+ zfs_file_t *fp;
+
+ fp = fget(fd);
+ if (fp == NULL)
+ return (EBADF);
+
+ *fpp = fp;
+
+ return (0);
+}
+
+/*
+ * Drop reference to file pointer
+ *
+ * fd - input file descriptor
+ */
+void
+zfs_file_put(int fd)
+{
+ struct file *fp;
+
+ if ((fp = fget(fd)) != NULL) {
+ fput(fp);
+ fput(fp);
+ }
+}
+#endif
+
diff --git a/enc_temp_folder/f34911e0bc429dd8d27b48f1bc3b52da/vdev_file.c b/enc_temp_folder/f34911e0bc429dd8d27b48f1bc3b52da/vdev_file.c
new file mode 100644
index 00000000..9f817c05
--- /dev/null
+++ b/enc_temp_folder/f34911e0bc429dd8d27b48f1bc3b52da/vdev_file.c
@@ -0,0 +1,757 @@
+/*
+ * CDDL HEADER START
+ *
+ * The contents of this file are subject to the terms of the
+ * Common Development and Distribution License (the "License").
+ * You may not use this file except in compliance with the License.
+ *
+ * You can obtain a copy of the license at usr/src/OPENSOLARIS.LICENSE
+ * or http://www.opensolaris.org/os/licensing.
+ * See the License for the specific language governing permissions
+ * and limitations under the License.
+ *
+ * When distributing Covered Code, include this CDDL HEADER in each
+ * file and include the License file at usr/src/OPENSOLARIS.LICENSE.
+ * If applicable, add the following below this CDDL HEADER, with the
+ * fields enclosed by brackets "[]" replaced with your own identifying
+ * information: Portions Copyright [yyyy] [name of copyright owner]
+ *
+ * CDDL HEADER END
+ */
+/*
+ * Copyright (c) 2005, 2010, Oracle and/or its affiliates. All rights reserved.
+ * Copyright (c) 2011, 2015 by Delphix. All rights reserved.
+ */
+
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+#include
+
+/*
+ * Virtual device vector for files.
+ */
+
+static taskq_t *vdev_file_taskq;
+
+extern void UnlockAndFreeMdl(PMDL);
+
+static void
+vdev_file_hold(vdev_t *vd)
+{
+ ASSERT(vd->vdev_path != NULL);
+}
+
+static void
+vdev_file_rele(vdev_t *vd)
+{
+ ASSERT(vd->vdev_path != NULL);
+}
+
+#ifdef _KERNEL
+extern int VOP_GETATTR(struct vnode *vp, vattr_t *vap, int flags, void *x3, void *x4);
+#endif
+
+//static int
+//vdev_file_open(vdev_t *vd, uint64_t *psize, uint64_t *max_psize,
+// uint64_t *ashift)
+//{
+//#if _KERNEL
+// static vattr_t vattr;
+// vdev_file_t *vf;
+//#endif
+// int error = 0;
+//
+// dprintf("vdev_file_open %p\n", vd->vdev_tsd);
+// /* Rotational optimizations only make sense on block devices */
+// vd->vdev_nonrot = B_TRUE;
+//
+// /*
+// * Allow TRIM on file based vdevs. This may not always be supported,
+// * since it depends on your kernel version and underlying filesystem
+// * type but it is always safe to attempt.
+// */
+// vd->vdev_has_trim = B_TRUE;
+//
+// /*
+// * Disable secure TRIM on file based vdevs. There is no way to
+// * request this behavior from the underlying filesystem.
+// */
+// vd->vdev_has_securetrim = B_FALSE;
+//
+// /*
+// * We must have a pathname, and it must be absolute.
+// */
+// if (vd->vdev_path == NULL || (vd->vdev_path[0] != '/' &&
+// vd->vdev_path[0] != '\\')) {
+// vd->vdev_stat.vs_aux = VDEV_AUX_BAD_LABEL;
+// return (SET_ERROR(EINVAL));
+// }
+//
+// /*
+// * Reopen the device if it's not currently open. Otherwise,
+// * just update the physical size of the device.
+// */
+//#ifdef _KERNEL
+// if (vd->vdev_tsd != NULL) {
+// ASSERT(vd->vdev_reopening);
+// vf = vd->vdev_tsd;
+// goto skip_open;
+// }
+//
+// vf = vd->vdev_tsd = kmem_zalloc(sizeof (vdev_file_t), KM_SLEEP);
+//#endif
+//
+// /*
+// * We always open the files from the root of the global zone, even if
+// * we're in a local zone. If the user has gotten to this point, the
+// * administrator has already decided that the pool should be available
+// * to local zone users, so the underlying devices should be as well.
+// */
+// ASSERT(vd->vdev_path != NULL && (
+// vd->vdev_path[0] == '/' || vd->vdev_path[0] == '\\'));
+//
+// /*
+// vn_openat(char *pnamep,
+// enum uio_seg seg,
+// int filemode,
+// int createmode,
+// struct vnode **vpp,
+// enum create crwhy,
+// mode_t umask,
+// struct vnode *startvp)
+// extern int vn_openat(char *pnamep, enum uio_seg seg, int filemode,
+// int createmode, struct vnode **vpp, enum create crwhy,
+// mode_t umask, struct vnode *startvp);
+// */
+// uint8_t *FileName = NULL;
+// FileName = vd->vdev_path;
+//
+// if (!strncmp("\\\\?\\", FileName, 4)) {
+// FileName[1] = '?';
+// }
+//
+// dprintf("%s: opening '%s'\n", __func__, FileName);
+//
+//#ifdef _KERNEL
+//
+// ANSI_STRING AnsiFilespec;
+// UNICODE_STRING UnicodeFilespec;
+// OBJECT_ATTRIBUTES ObjectAttributes;
+//
+// SHORT UnicodeName[PATH_MAX];
+// CHAR AnsiName[PATH_MAX];
+// USHORT NameLength = 0;
+// NTSTATUS ntstatus;
+//
+// memset(UnicodeName, 0, sizeof(SHORT) * PATH_MAX);
+// memset(AnsiName, 0, sizeof(UCHAR) * PATH_MAX);
+//
+// NameLength = strlen(FileName);
+// ASSERT(NameLength < PATH_MAX);
+//
+// memmove(AnsiName, FileName, NameLength);
+//
+// AnsiFilespec.MaximumLength = AnsiFilespec.Length = NameLength;
+// AnsiFilespec.Buffer = AnsiName;
+//
+// UnicodeFilespec.MaximumLength = PATH_MAX * 2;
+// UnicodeFilespec.Length = 0;
+// UnicodeFilespec.Buffer = (PWSTR)UnicodeName;
+//
+// RtlAnsiStringToUnicodeString(&UnicodeFilespec, &AnsiFilespec, FALSE);
+//
+// ObjectAttributes.Length = sizeof(OBJECT_ATTRIBUTES);
+// ObjectAttributes.RootDirectory = NULL;
+// ObjectAttributes.Attributes = /*OBJ_CASE_INSENSITIVE |*/ OBJ_KERNEL_HANDLE;
+// ObjectAttributes.ObjectName = &UnicodeFilespec;
+// ObjectAttributes.SecurityDescriptor = NULL;
+// ObjectAttributes.SecurityQualityOfService = NULL;
+// IO_STATUS_BLOCK iostatus;
+//
+// ntstatus = ZwCreateFile(&vf->vf_handle,
+// spa_mode(vd->vdev_spa) == FREAD ? GENERIC_READ | SYNCHRONIZE : GENERIC_READ | GENERIC_WRITE | SYNCHRONIZE,
+// &ObjectAttributes,
+// &iostatus,
+// 0,
+// FILE_ATTRIBUTE_NORMAL,
+// /* FILE_SHARE_WRITE | */ FILE_SHARE_READ,
+// FILE_OPEN,
+// FILE_SYNCHRONOUS_IO_NONALERT | (spa_mode(vd->vdev_spa) == FREAD ? 0 : FILE_NO_INTERMEDIATE_BUFFERING),
+// NULL,
+// 0);
+//
+// if (ntstatus == STATUS_SUCCESS) {
+// error = 0;
+// } else {
+// vd->vdev_stat.vs_aux = VDEV_AUX_OPEN_FAILED;
+// goto failed;
+// }
+//
+//
+// /*
+// * Make sure it's a regular file.
+// */
+// FILE_STANDARD_INFORMATION info;
+// IO_STATUS_BLOCK iob;
+//
+// if ((ZwQueryInformationFile(
+// vf->vf_handle,
+// &iob,
+// &info,
+// sizeof(info),
+// FileStandardInformation) != STATUS_SUCCESS) ||
+// (info.Directory != FALSE)) {
+// vd->vdev_stat.vs_aux = VDEV_AUX_OPEN_FAILED;
+// ZwClose(vf->vf_handle);
+// error = ENOENT;
+// goto failed;
+// }
+//
+// // Since we will use DeviceObject and FileObject to do ioctl and IO
+// // we grab them now and lock them in place.
+// // Convert HANDLE to FileObject
+// PFILE_OBJECT FileObject;
+// PDEVICE_OBJECT DeviceObject;
+// NTSTATUS status;
+//
+// // This adds a reference to FileObject
+// status = ObReferenceObjectByHandle(
+// vf->vf_handle,
+// 0,
+// *IoFileObjectType,
+// KernelMode,
+// &FileObject,
+// NULL
+// );
+// if (status != STATUS_SUCCESS) {
+// ZwClose(vf->vf_handle);
+// vd->vdev_stat.vs_aux = VDEV_AUX_OPEN_FAILED;
+// error = EIO;
+// goto failed;
+// }
+//
+// // Convert FileObject to DeviceObject
+// DeviceObject = IoGetRelatedDeviceObject(FileObject);
+//
+// // Grab a reference to DeviceObject
+// ObReferenceObject(DeviceObject);
+//
+// vf->vf_FileObject = FileObject;
+// vf->vf_DeviceObject = DeviceObject;
+//
+// // Change it to SPARSE, so TRIM might work
+// status = ZwFsControlFile(
+// vf->vf_handle,
+// NULL,
+// NULL,
+// NULL,
+// NULL,
+// FSCTL_SET_SPARSE,
+// NULL,
+// 0,
+// NULL,
+// 0
+// );
+// dprintf("%s: set Sparse 0x%x.\n", __func__, status);
+//
+//#endif
+//
+//#if _KERNEL
+//skip_open:
+// /*
+// * Determine the physical size of the file.
+// */
+// //vattr.va_mask = AT_SIZE;
+// //vn_lock(vf->vf_vnode, LK_SHARED | LK_RETRY);
+// //error = VOP_GETATTR(vf->vf_vnode, &vattr, 0, kcred, NULL);
+// //VN_UNLOCK(vf->vf_vnode);
+//#endif
+//
+//#ifdef _KERNEL
+// *max_psize = *psize = info.EndOfFile.QuadPart;
+//#else
+// /* userland's vn_open() will get the device size for us, so we can
+// * just look it up - there is argument for a userland VOP_GETATTR to make
+// * this function cleaner. */
+//// *max_psize = *psize = vp->v_size;
+//#endif
+// *ashift = SPA_MINBLOCKSHIFT;
+//
+// return (0);
+//
+//failed:
+//#ifdef _KERNEL
+// if (vf) {
+// if (vf->vf_handle != NULL) {
+// vf->vf_handle = NULL;
+// }
+//
+// kmem_free(vf, sizeof(vdev_file_t));
+// vd->vdev_tsd = NULL;
+// }
+//#endif
+// return error;
+//}
+
+static mode_t vdev_file_open_mode(spa_mode_t spa_mode)
+{
+ mode_t mode = 0;
+ // TODO :- Add flags
+ if ((spa_mode & SPA_MODE_READ) && (spa_mode & SPA_MODE_WRITE)) {
+ mode = O_RDWR;
+ }
+ else if (spa_mode & SPA_MODE_READ) {
+ mode = O_RDONLY;
+ }
+ else if (spa_mode & SPA_MODE_WRITE) {
+ mode = O_WRONLY;
+ }
+ return mode;
+}
+
+static int
+vdev_file_open(vdev_t* vd, uint64_t* psize, uint64_t* max_psize,
+ uint64_t* ashift)
+{
+ vdev_file_t2* vf;
+ zfs_file_t fp;
+ zfs_file_attr_t zfa;
+ int err;
+
+ /*
+ * Rotational optimizations only make sense on block devices.
+ */
+ vd->vdev_nonrot = B_TRUE;
+
+ /*
+ * Allow TRIM on file based vdevs. This may not always be supported,
+ * since it depends on your kernel version and underlying filesystem
+ * type but it is always safe to attempt.
+ */
+ vd->vdev_has_trim = B_TRUE;
+
+ /*
+ * Disable secure TRIM on file based vdevs. There is no way to
+ * request this behavior from the underlying filesystem.
+ */
+ vd->vdev_has_securetrim = B_FALSE;
+
+ /*
+ * We must have a pathname, and it must be absolute.
+ */
+
+ if (vd->vdev_path == NULL || (vd->vdev_path[0] != '/' && vd->vdev_path[0] != '\\')) {
+ vd->vdev_stat.vs_aux = VDEV_AUX_BAD_LABEL;
+ return (SET_ERROR(EINVAL));
+ }
+
+ if (vd->vdev_tsd != NULL) {
+ ASSERT(vd->vdev_reopening);
+ vf = vd->vdev_tsd;
+ goto skip_open;
+ }
+
+ vf = vd->vdev_tsd = kmem_zalloc(sizeof(vdev_file_t2), KM_SLEEP);
+ ASSERT(vd->vdev_path != NULL && (
+ vd->vdev_path[0] == '/' || vd->vdev_path[0] == '\\'));
+
+ vd->vdev_path = "\\\\.\\PhysicalDrive1";
+ err = zfs_file_open(vd->vdev_path, vdev_file_open_mode(spa_mode(vd->vdev_spa)), 0, &fp);
+ if (err) {
+ vd->vdev_stat.vs_aux = VDEV_AUX_OPEN_FAILED;
+ return (err);
+ }
+ vf->vf_file = fp;
+
+ //#ifdef _KERNEL
+ // /*
+ // * Make sure it's a regular file.
+ // */
+ // if (zfs_file_getattr(fp, &zfa)) {
+ // return (SET_ERROR(ENODEV));
+ // }
+ // if (!S_ISREG(zfa.zfa_mode)) {
+ // vd->vdev_stat.vs_aux = VDEV_AUX_OPEN_FAILED;
+ // return (SET_ERROR(ENODEV));
+ // }
+ //#endif
+skip_open:
+#ifdef _KERNEL
+ err = zfs_file_getattr(vf->vf_file, &zfa);
+ if (err) {
+ vd->vdev_stat.vs_aux = VDEV_AUX_OPEN_FAILED;
+ return (err);
+ }
+#else
+ err = zfs_file_geomtery(&fp, &zfa);
+#endif
+ * max_psize = *psize = zfa.zfa_size;
+ *ashift = SPA_MINBLOCKSHIFT;
+ return (0);
+}
+
+//static void
+//vdev_file_close(vdev_t *vd)
+//{
+//#ifdef _KERNEL
+// vdev_file_t *vf = vd->vdev_tsd;
+//
+// if (vd->vdev_reopening || vf == NULL)
+// return;
+//
+// if (vf->vf_handle != NULL) {
+//
+// // Release our holds
+// ObDereferenceObject(vf->vf_FileObject);
+// ObDereferenceObject(vf->vf_DeviceObject);
+//
+// ZwClose(vf->vf_handle);
+// }
+//
+// vf->vf_FileObject = NULL;
+// vf->vf_DeviceObject = NULL;
+// vf->vf_handle = NULL;
+// vd->vdev_delayed_close = B_FALSE;
+// kmem_free(vf, sizeof (vdev_file_t));
+// vd->vdev_tsd = NULL;
+//#endif
+//}
+
+static void vdev_file_close(vdev_t* vd)
+{
+ vdev_file_t2* vf = vd->vdev_tsd;
+
+ if (vd->vdev_reopening || vf == NULL)
+ return;
+
+ if (vf->vf_file != NULL) {
+ (void)zfs_file_close(&vf->vf_file);
+ }
+ vd->vdev_delayed_close = B_FALSE;
+ kmem_free(vf, sizeof(vdev_file_t2));
+ vd->vdev_tsd = NULL;
+}
+
+#ifdef _KERNEL
+struct vdev_file_callback_struct {
+ zio_t *zio;
+ PIRP irp;
+ void *b_data;
+ char work_item[0];
+};
+typedef struct vdev_file_callback_struct vf_callback_t;
+
+static void
+vdev_file_io_start_done(void *param)
+{
+ vf_callback_t *vb = (vf_callback_t *)param;
+
+ ASSERT(vb != NULL);
+
+ NTSTATUS status = vb->irp->IoStatus.Status;
+ zio_t *zio = vb->zio;
+ zio->io_error = (!NT_SUCCESS(status) ? EIO : 0);
+
+ // Return abd buf
+ if (zio->io_type == ZIO_TYPE_READ) {
+ VERIFY3S(zio->io_abd->abd_size, >= , zio->io_size);
+ abd_return_buf_copy_off(zio->io_abd, vb->b_data,
+ 0, zio->io_size, zio->io_abd->abd_size);
+ } else {
+ VERIFY3S(zio->io_abd->abd_size, >= , zio->io_size);
+ abd_return_buf_off(zio->io_abd, vb->b_data,
+ 0, zio->io_size, zio->io_abd->abd_size);
+ }
+
+ UnlockAndFreeMdl(vb->irp->MdlAddress);
+ IoFreeIrp(vb->irp);
+ kmem_free(vb, sizeof(vf_callback_t) + IoSizeofWorkItem());
+ vb = NULL;
+ zio_delay_interrupt(zio);
+}
+
+static VOID
+FileIoWkRtn(
+ __in PVOID pDummy, // Not used.
+ __in PVOID pWkParms // Parm list pointer.
+)
+{
+ vf_callback_t *vb = (vf_callback_t *)pWkParms;
+
+ UNREFERENCED_PARAMETER(pDummy);
+ IoUninitializeWorkItem((PIO_WORKITEM)vb->work_item);
+ vdev_file_io_start_done(vb);
+}
+
+static NTSTATUS
+vdev_file_io_intrxxx(PDEVICE_OBJECT DeviceObject, PIRP irp, PVOID Context)
+{
+ vf_callback_t *vb = (vf_callback_t *)Context;
+
+ ASSERT(vb != NULL);
+
+ /* If IRQL is below DIPATCH_LEVEL then there is no issue in calling
+ * vdev_file_io_start_done() directly; otherwise queue a new Work Item
+ */
+ if (KeGetCurrentIrql() < DISPATCH_LEVEL)
+ vdev_file_io_start_done(vb);
+ else {
+ vdev_file_t *vf = vb->zio->io_vd->vdev_tsd;
+ IoInitializeWorkItem(vf->vf_DeviceObject, (PIO_WORKITEM)vb->work_item);
+ IoQueueWorkItem((PIO_WORKITEM)vb->work_item, FileIoWkRtn, DelayedWorkQueue, vb);
+ }
+
+ return STATUS_MORE_PROCESSING_REQUIRED;
+}
+#endif
+
+/*
+ * count the number of mismatches of zio->io_size and zio->io_abd->abd_size below
+ */
+_Atomic uint64_t zfs_vdev_file_size_mismatch_cnt = 0;
+
+// clear the changes
+static void
+vdev_file_io_start(zio_t *zio)
+{
+ vdev_t *vd = zio->io_vd;
+ ssize_t resid = 0;
+
+
+ if (zio->io_type == ZIO_TYPE_IOCTL) {
+
+ if (!vdev_readable(vd)) {
+ zio->io_error = SET_ERROR(ENXIO);
+ zio_interrupt(zio);
+ return;
+ }
+
+ switch (zio->io_cmd) {
+ case DKIOCFLUSHWRITECACHE:
+#if 0
+ if (!vnode_getwithvid(vf->vf_vnode, vf->vf_vid)) {
+ zio->io_error = VOP_FSYNC(vf->vf_vnode, FSYNC | FDSYNC,
+ kcred, NULL);
+ vnode_put(vf->vf_vnode);
+ }
+#endif
+ break;
+ default:
+ zio->io_error = SET_ERROR(ENOTSUP);
+ }
+
+ zio_interrupt(zio);
+ return;
+
+ } else if (zio->io_type == ZIO_TYPE_TRIM) {
+#ifdef _KERNEL
+ struct flock flck;
+ vdev_file_t *vf = vd->vdev_tsd;
+
+ ASSERT3U(zio->io_size, != , 0);
+ bzero(&flck, sizeof(flck));
+ flck.l_type = F_FREESP;
+ flck.l_start = zio->io_offset;
+ flck.l_len = zio->io_size;
+ flck.l_whence = 0;
+
+ zio->io_error = VOP_SPACE(vf->vf_handle, F_FREESP, &flck,
+ 0, 0, kcred, NULL);
+
+#endif
+ zio_execute(zio);
+ return;
+ }
+
+ ASSERT(zio->io_type == ZIO_TYPE_READ || zio->io_type == ZIO_TYPE_WRITE);
+ zio->io_target_timestamp = zio_handle_io_delay(zio);
+
+
+ ASSERT(zio->io_size != 0);
+
+#ifdef _KERNEL
+ vdev_file_t* vf = vd->vdev_tsd;
+#else
+ vdev_file_t2* vf = vd->vdev_tsd;
+#endif // _KERNEL
+ LARGE_INTEGER offset;
+ offset.QuadPart = zio->io_offset + vd->vdev_win_offset;
+#ifdef _KERNEL
+ PIRP irp = NULL;
+ PIO_STACK_LOCATION irpStack = NULL;
+ IO_STATUS_BLOCK IoStatusBlock = { 0 };
+
+
+ /* Preallocate space for IoWorkItem, required for vdev_file_io_start_done callback */
+ vf_callback_t *vb = (vf_callback_t *)kmem_alloc(sizeof(vf_callback_t) + IoSizeofWorkItem(), KM_SLEEP);
+
+ vb->zio = zio;
+
+#ifdef DEBUG
+ if (zio->io_abd->abd_size != zio->io_size) {
+ zfs_vdev_file_size_mismatch_cnt++;
+ // this dprintf can be very noisy
+ dprintf("ZFS: %s: trimming zio->io_abd from 0x%x to 0x%llx\n",
+ __func__, zio->io_abd->abd_size, zio->io_size);
+ }
+#endif
+
+ if (zio->io_type == ZIO_TYPE_READ) {
+ ASSERT3S(zio->io_abd->abd_size, >= , zio->io_size);
+ vb->b_data =
+ abd_borrow_buf(zio->io_abd, zio->io_abd->abd_size);
+ } else {
+ ASSERT3S(zio->io_abd->abd_size, >= , zio->io_size);
+ vb->b_data =
+ abd_borrow_buf_copy(zio->io_abd, zio->io_abd->abd_size);
+ }
+
+ if (zio->io_type == ZIO_TYPE_READ) {
+ irp = IoBuildAsynchronousFsdRequest(IRP_MJ_READ,
+ vf->vf_DeviceObject,
+ vb->b_data,
+ (ULONG)zio->io_size,
+ &offset,
+ &IoStatusBlock);
+ } else {
+ irp = IoBuildAsynchronousFsdRequest(IRP_MJ_WRITE,
+ vf->vf_DeviceObject,
+ vb->b_data,
+ (ULONG)zio->io_size,
+ &offset,
+ &IoStatusBlock);
+ }
+
+ if (!irp) {
+ kmem_free(vb, sizeof(vf_callback_t) + IoSizeofWorkItem());
+ zio->io_error = EIO;
+ zio_interrupt(zio);
+ return;
+ }
+
+ irpStack = IoGetNextIrpStackLocation(irp);
+
+ irpStack->Flags |= SL_OVERRIDE_VERIFY_VOLUME; // SetFlag(IoStackLocation->Flags, SL_OVERRIDE_VERIFY_VOLUME);
+ //SetFlag(ReadIrp->Flags, IRP_NOCACHE);
+ irpStack->FileObject = vf->vf_FileObject;
+
+ IoSetCompletionRoutine(irp,
+ vdev_file_io_intrxxx,
+ vb, // "Context" in vdev_file_io_intr()
+ TRUE, // On Success
+ TRUE, // On Error
+ TRUE);// On Cancel
+
+ IoCallDriver(vf->vf_DeviceObject, irp);
+#else
+ void* data;
+ int err;
+ DWORD red;
+ HANDLE hFile = vf->vf_file;
+
+ if (!SetFilePointerEx(hFile, offset, NULL, FILE_BEGIN))
+ goto failed;
+
+ if (zio->io_type == ZIO_TYPE_READ) {
+ ASSERT3S(zio->io_abd->abd_size, >= , zio->io_size);
+ //data =
+ // abd_borrow_buf(zio->io_abd, zio->io_abd->abd_size);
+ //ok = ReadFile(hFile, data, zio->io_size, &red, NULL);
+ //abd_return_buf_copy(zio->io_abd, data, zio->io_size);
+ data = abd_borrow_buf(zio->io_abd, zio->io_abd->abd_size);
+ err = ReadFile(hFile, data, zio->io_size, &red, NULL);
+ //err = zfs_file_pread(&hFile, data, zio->io_size, &red, zio->io_offset);
+ abd_return_buf_copy(zio->io_abd, data, zio->io_size); // see in kernel space what is happening
+ }
+ else {
+ ASSERT3S(zio->io_abd->abd_size, >= , zio->io_size);
+ data =
+ abd_borrow_buf_copy(zio->io_abd, zio->io_abd->abd_size);
+ err = WriteFile(hFile, data, zio->io_size, &red, NULL);
+ abd_return_buf_off(zio->io_abd, data,
+ 0, zio->io_size, zio->io_abd->abd_size);
+ }
+
+failed:
+ if (!err)
+ zio->io_error = EIO;
+ else if (red != zio->io_size)
+ zio->io_error = SET_ERROR(ENOSPC);
+ else
+ zio->io_error = 0;
+
+ zio_delay_interrupt(zio);
+ return;
+#endif
+
+ return;
+}
+
+
+/* ARGSUSED */
+static void
+vdev_file_io_done(zio_t *zio)
+{
+}
+
+vdev_ops_t vdev_file_ops = {
+ vdev_file_open,
+ vdev_file_close,
+ vdev_default_asize,
+ vdev_file_io_start,
+ vdev_file_io_done,
+ NULL,
+ NULL,
+ vdev_file_hold,
+ vdev_file_rele,
+ NULL,
+ vdev_default_xlate,
+ VDEV_TYPE_FILE, /* name of this vdev type */
+ B_TRUE /* leaf vdev */
+};
+
+void
+vdev_file_init(void)
+{
+ vdev_file_taskq = taskq_create("vdev_file_taskq", 100, minclsyspri,
+ max_ncpus, INT_MAX, TASKQ_PREPOPULATE | TASKQ_THREADS_CPU_PCT);
+
+ VERIFY(vdev_file_taskq);
+}
+
+void
+vdev_file_fini(void)
+{
+ taskq_destroy(vdev_file_taskq);
+}
+
+/*
+ * From userland we access disks just like files.
+ */
+#ifndef _KERNEL
+
+vdev_ops_t vdev_disk_ops = {
+ vdev_file_open,
+ vdev_file_close,
+ vdev_default_asize,
+ vdev_file_io_start,
+ vdev_file_io_done,
+ NULL,
+ NULL,
+ vdev_file_hold,
+ vdev_file_rele,
+ NULL,
+ vdev_default_xlate,
+ VDEV_TYPE_DISK, /* name of this vdev type */
+ B_TRUE /* leaf vdev */
+};
+
+#endif