2
0
mirror of https://github.com/dominicusin/zfs-win synced 2025-08-22 10:09:42 +00:00

Just uploading some initial code, it can read objects until the root dir.

No error checking and little-endian only.
This commit is contained in:
gabest11 2010-07-22 04:28:38 +00:00
commit 1150b29fbe
25 changed files with 3665 additions and 0 deletions

25
common.props Normal file
View File

@ -0,0 +1,25 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ImportGroup Label="PropertySheets" />
<PropertyGroup Label="UserMacros" />
<PropertyGroup>
<OutDir>$(SolutionDir)bin\$(Configuration)\</OutDir>
<LinkIncremental>false</LinkIncremental>
</PropertyGroup>
<ItemDefinitionGroup>
<ClCompile>
<DebugInformationFormat>ProgramDatabase</DebugInformationFormat>
<WarningLevel>Level3</WarningLevel>
<PreprocessorDefinitions>WIN32;_WINDOWS;RESTRICT=__restrict;_USE_MATH_DEFINES;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<DisableSpecificWarnings>4091;4995;4996;4793;4100;4512</DisableSpecificWarnings>
<StringPooling>true</StringPooling>
<FunctionLevelLinking>true</FunctionLevelLinking>
<MultiProcessorCompilation>true</MultiProcessorCompilation>
<MinimalRebuild>false</MinimalRebuild>
</ClCompile>
<Link>
<GenerateDebugInformation>true</GenerateDebugInformation>
</Link>
</ItemDefinitionGroup>
<ItemGroup />
</Project>

16
debug.props Normal file
View File

@ -0,0 +1,16 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ImportGroup Label="PropertySheets" />
<PropertyGroup Label="UserMacros" />
<ItemDefinitionGroup>
<ClCompile>
<Optimization>Disabled</Optimization>
<RuntimeLibrary>MultiThreadedDebugDLL</RuntimeLibrary>
<PreprocessorDefinitions>_DEBUG;DEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
<Link>
<AssemblyDebug>true</AssemblyDebug>
</Link>
</ItemDefinitionGroup>
<ItemGroup />
</Project>

26
release.props Normal file
View File

@ -0,0 +1,26 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ImportGroup Label="PropertySheets" />
<PropertyGroup Label="UserMacros" />
<ItemDefinitionGroup>
<ClCompile>
<Optimization>MaxSpeed</Optimization>
<InlineFunctionExpansion>AnySuitable</InlineFunctionExpansion>
<IntrinsicFunctions>true</IntrinsicFunctions>
<FavorSizeOrSpeed>Speed</FavorSizeOrSpeed>
<OmitFramePointers>true</OmitFramePointers>
<WholeProgramOptimization>true</WholeProgramOptimization>
<RuntimeLibrary>MultiThreadedDLL</RuntimeLibrary>
<PreprocessorDefinitions>_SECURE_SCL=0;NDEBUG;%(PreprocessorDefinitions)</PreprocessorDefinitions>
<BufferSecurityCheck>false</BufferSecurityCheck>
</ClCompile>
<Link>
<OptimizeReferences>true</OptimizeReferences>
<EnableCOMDATFolding>true</EnableCOMDATFolding>
</Link>
<Lib>
<LinkTimeCodeGeneration>true</LinkTimeCodeGeneration>
</Lib>
</ItemDefinitionGroup>
<ItemGroup />
</Project>

20
zfs-win.sln Normal file
View File

@ -0,0 +1,20 @@

Microsoft Visual Studio Solution File, Format Version 11.00
# Visual Studio 2010
Project("{8BC9CEB8-8B4A-11D0-8D11-00A0C91BC942}") = "zfs-win", "zfs-win\zfs-win.vcxproj", "{4A7767E8-F121-4CA9-9147-D3B29A0F831E}"
EndProject
Global
GlobalSection(SolutionConfigurationPlatforms) = preSolution
Debug|Win32 = Debug|Win32
Release|Win32 = Release|Win32
EndGlobalSection
GlobalSection(ProjectConfigurationPlatforms) = postSolution
{4A7767E8-F121-4CA9-9147-D3B29A0F831E}.Debug|Win32.ActiveCfg = Debug|Win32
{4A7767E8-F121-4CA9-9147-D3B29A0F831E}.Debug|Win32.Build.0 = Debug|Win32
{4A7767E8-F121-4CA9-9147-D3B29A0F831E}.Release|Win32.ActiveCfg = Release|Win32
{4A7767E8-F121-4CA9-9147-D3B29A0F831E}.Release|Win32.Build.0 = Release|Win32
EndGlobalSection
GlobalSection(SolutionProperties) = preSolution
HideSolutionNode = FALSE
EndGlobalSection
EndGlobal

164
zfs-win/BlockReader.cpp Normal file
View File

@ -0,0 +1,164 @@
/*
* Copyright (C) 2010 Gabest
* http://code.google.com/p/zfs-win/
*
* This Program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This Program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GNU Make; see the file COPYING. If not, write to
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
* http://www.gnu.org/copyleft/gpl.html
*
*/
#include "stdafx.h"
#include "BlockReader.h"
#include "Compress.h"
namespace ZFS
{
BlockReader::BlockReader(Pool* pool, blkptr_t* bp, size_t count)
: m_pool(pool)
{
Insert(bp, count);
}
BlockReader::~BlockReader()
{
for(auto i = m_bpl.begin(); i != m_bpl.end(); i++)
{
delete *i;
}
}
bool BlockReader::ReadNext(std::vector<uint8_t>& buff)
{
if(m_bpl.empty())
{
return false;
}
std::auto_ptr<blkptr_t> bp(m_bpl.front());
m_bpl.pop_front();
while(bp->lvl > 0)
{
if(!Read(bp.get(), buff))
{
return false;
}
Insert((blkptr_t*)buff.data(), buff.size() / sizeof(blkptr_t));
bp = std::auto_ptr<blkptr_t>(m_bpl.front());
m_bpl.pop_front();
}
return Read(bp.get(), buff);
}
bool BlockReader::ReadToEnd(std::vector<uint8_t>& dst)
{
dst.clear();
// TODO: resize/reserve (how much?)
size_t i = 0;
std::vector<uint8_t> buff;
while(ReadNext(buff))
{
if(i + buff.size() > dst.size())
{
dst.resize(i + buff.size());
}
memcpy(dst.data() + i, buff.data(), buff.size());
i += buff.size();
}
return true;
}
void BlockReader::Insert(blkptr_t* bp, size_t count)
{
if(m_bpl.empty())
{
for(size_t i = 0; i < count && bp[i].type != DMU_OT_NONE; i++)
{
m_bpl.push_back(new blkptr_t(bp[i]));
}
}
else
{
std::list<blkptr_t*> l;
for(size_t i = 0; i < count && bp[i].type != DMU_OT_NONE; i++)
{
l.push_back(new blkptr_t(bp[i]));
}
m_bpl.insert(m_bpl.begin(), l.begin(), l.end());
}
}
bool BlockReader::Read(blkptr_t* bp, std::vector<uint8_t>& dst)
{
for(int i = 0; i < 3; i++)
{
dva_t* addr = &bp->blk_dva[i];
ASSERT(addr->gang == 0); // TODO: zio_gbh_phys_t (not used ??? never encountered one, yet)
for(auto i = m_pool->m_vdevs.begin(); i != m_pool->m_vdevs.end(); i++)
{
VirtualDevice* vdev = *i;
if(vdev->id != addr->vdev)
{
continue;
}
size_t psize = (size_t)(bp->psize + 1) << 9;
size_t lsize = (size_t)(bp->lsize + 1) << 9;
std::vector<uint8_t> src(psize);
vdev->Read(src, psize, addr->offset << 9);
// TODO: verify bp->chksum
switch(bp->comp)
{
case ZIO_COMPRESS_ON:
case ZIO_COMPRESS_LZJB:
dst.resize(lsize);
lzjb_decompress(src.data(), dst.data(), psize, lsize);
break;
case ZIO_COMPRESS_OFF:
dst.swap(src);
break;
default: // TODO: gzip, zle
ASSERT(0);
return false;
}
return true;
}
}
return false;
}
}

47
zfs-win/BlockReader.h Normal file
View File

@ -0,0 +1,47 @@
/*
* Copyright (C) 2010 Gabest
* http://code.google.com/p/zfs-win/
*
* This Program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This Program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GNU Make; see the file COPYING. If not, write to
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
* http://www.gnu.org/copyleft/gpl.html
*
*/
#pragma once
#include "zfs.h"
#include "Pool.h"
#include "Device.h"
namespace ZFS
{
class BlockReader
{
Pool* m_pool;
std::list<blkptr_t*> m_bpl;
void Insert(blkptr_t* bp, size_t count);
bool Read(blkptr_t* bp, std::vector<uint8_t>& buff);
public:
BlockReader(Pool* pool, blkptr_t* bp, size_t count);
virtual ~BlockReader();
bool ReadNext(std::vector<uint8_t>& buff);
bool ReadToEnd(std::vector<uint8_t>& buff);
// TODO: function to read only part of the whole data (for large files)
};
}

155
zfs-win/Compress.cpp Normal file
View File

@ -0,0 +1,155 @@
/*
* 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.
*/
#include "stdafx.h"
#include "Compress.h"
#define NBBY 8
#define MATCH_BITS 6
#define MATCH_MIN 3
#define MATCH_MAX ((1 << MATCH_BITS) + (MATCH_MIN - 1))
#define OFFSET_MASK ((1 << (16 - MATCH_BITS)) - 1)
#define LEMPEL_SIZE 1024
/*
* We keep our own copy of this algorithm for 3 main reasons:
* 1. If we didn't, anyone modifying common/os/compress.c would
* directly break our on disk format
* 2. Our version of lzjb does not have a number of checks that the
* common/os version needs and uses
* 3. We initialize the lempel to ensure deterministic results,
* so that identical blocks can always be deduplicated.
* In particular, we are adding the "feature" that compress() can
* take a destination buffer size and returns the compressed length, or the
* source length if compression would overflow the destination buffer.
*/
size_t lzjb_compress(void* s_start, void* d_start, size_t s_len, size_t d_len)
{
uint8_t* src = (uint8_t*)s_start;
uint8_t* dst = (uint8_t*)d_start;
uint8_t* cpy;
uint8_t* copymap;
int copymask = 1 << (NBBY - 1);
int mlen, offset, hash;
uint16_t* hp;
uint16_t lempel[LEMPEL_SIZE] = { 0 };
while(src < (uint8_t*)s_start + s_len)
{
if((copymask <<= 1) == (1 << NBBY))
{
if(dst >= (uint8_t *)d_start + d_len - 1 - 2 * NBBY)
{
return s_len;
}
copymask = 1;
copymap = dst;
*dst++ = 0;
}
if(src > (uint8_t*)s_start + s_len - MATCH_MAX)
{
*dst++ = *src++;
continue;
}
hash = (src[0] << 16) + (src[1] << 8) + src[2];
hash += hash >> 9;
hash += hash >> 5;
hp = &lempel[hash & (LEMPEL_SIZE - 1)];
offset = (intptr_t)(src - *hp) & OFFSET_MASK;
*hp = (uint16_t)(uintptr_t)src;
cpy = src - offset;
if(cpy >= (uint8_t *)s_start && cpy != src && src[0] == cpy[0] && src[1] == cpy[1] && src[2] == cpy[2])
{
*copymap |= copymask;
for(mlen = MATCH_MIN; mlen < MATCH_MAX; mlen++)
{
if(src[mlen] != cpy[mlen])
{
break;
}
}
*dst++ = ((mlen - MATCH_MIN) << (NBBY - MATCH_BITS)) | (offset >> NBBY);
*dst++ = (uint8_t)offset;
src += mlen;
}
else
{
*dst++ = *src++;
}
}
return dst - (uint8_t*)d_start;
}
int lzjb_decompress(void* s_start, void* d_start, size_t s_len, size_t d_len)
{
uint8_t* src = (uint8_t*)s_start;
uint8_t* dst = (uint8_t*)d_start;
uint8_t* d_end = (uint8_t*)d_start + d_len;
uint8_t* cpy;
uint8_t copymap;
int copymask = 1 << (NBBY - 1);
while(dst < d_end)
{
if((copymask <<= 1) == (1 << NBBY))
{
copymask = 1;
copymap = *src++;
}
if(copymap & copymask)
{
int mlen = (src[0] >> (NBBY - MATCH_BITS)) + MATCH_MIN;
int offset = ((src[0] << NBBY) | src[1]) & OFFSET_MASK;
src += 2;
if((cpy = dst - offset) < (uint8_t*)d_start)
{
return -1;
}
while(--mlen >= 0 && dst < d_end)
{
*dst++ = *cpy++;
}
}
else
{
*dst++ = *src++;
}
}
return 0;
}

31
zfs-win/Compress.h Normal file
View File

@ -0,0 +1,31 @@
/*
* 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 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
#pragma once
extern size_t lzjb_compress(void* s_start, void* d_start, size_t s_len, size_t d_len);
extern int lzjb_decompress(void* s_start, void* d_start, size_t s_len, size_t d_len);
// TODO: gzip, zle

351
zfs-win/Device.cpp Normal file
View File

@ -0,0 +1,351 @@
/*
* Copyright (C) 2010 Gabest
* http://code.google.com/p/zfs-win/
*
* This Program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This Program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GNU Make; see the file COPYING. If not, write to
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
* http://www.gnu.org/copyleft/gpl.html
*
*/
#include "stdafx.h"
#include "Device.h"
namespace ZFS
{
// VirtualDevice
void VirtualDevice::Init(NameValueList* nvl)
{
dev = NULL;
type = nvl->at("type")->str[0];
id = nvl->at("id")->u64[0];
guid = nvl->at("guid")->u64[0];
metaslab_array = nvl->find("metaslab_array") != nvl->end() ? nvl->at("metaslab_array")->u64[0] : 0;
metaslab_shift = nvl->find("metaslab_shift") != nvl->end() ? nvl->at("metaslab_shift")->u64[0] : 0;
ashift = nvl->find("ashift") != nvl->end() ? nvl->at("ashift")->u64[0] : 0;
asize = nvl->find("asize") != nvl->end() ? nvl->at("asize")->u64[0] : 0;
if(nvl->find("path") != nvl->end()) path = nvl->at("path")->str[0];
if(nvl->find("devid") != nvl->end()) devid = nvl->at("devid")->str[0];
nparity = nvl->find("nparity") != nvl->end() ? nvl->at("nparity")->u64[0] : 0;
whole_disk = nvl->find("whole_disk") != nvl->end() ? nvl->at("whole_disk")->u64[0] : 0;
is_log = nvl->find("is_log") != nvl->end() ? nvl->at("is_log")->u64[0] : 0;
if(nvl->find("children") != nvl->end())
{
NameValuePair* nvp = nvl->at("children");
children.resize(nvp->count);
for(uint32_t i = 0; i < nvp->count; i++)
{
children[i].Init(&nvp->list[i]);
}
}
}
bool VirtualDevice::Read(std::vector<uint8_t>& buff, uint64_t size, uint64_t offset)
{
// TODO: handle chksum errors
buff.resize((size_t)size);
if(type == "disk" || type == "file")
{
if(dev != NULL)
{
dev->Seek(offset + 0x400000);
if(dev->Read(buff.data(), size) == size)
{
return true;
}
}
}
else if(type == "mirror")
{
for(auto i = children.begin(); i != children.end(); i++)
{
VirtualDevice& vdev = *i;
if(vdev.dev != NULL)
{
dev->Seek(offset + 0x400000);
if(dev->Read(buff.data(), size) == size)
{
return true;
}
}
}
}
else if(type == "raidz")
{
raidz_map_t rm(offset, size, (uint32_t)ashift, children.size(), (uint32_t)nparity);
uint64_t total = 0;
for(size_t i = 1; i < rm.m_col.size(); i++)
{
total += rm.m_col[i].size;
}
if(total > buff.size())
{
return false;
}
uint8_t* p = buff.data();
for(size_t i = 1; i < rm.m_col.size(); i++)
{
VirtualDevice& vdev = children[(size_t)rm.m_col[i].devidx];
// TODO: reconstruct data if vdev.dev is missing or Read fails
if(vdev.dev != NULL)
{
vdev.dev->Seek(rm.m_col[i].offset + 0x400000);
if(!vdev.dev->Read(p, rm.m_col[i].size) != rm.m_col[i].size)
{
return false;
}
}
p += rm.m_col[i].size;
}
return true;
}
else
{
ASSERT(0);
}
return false;
}
VirtualDevice* VirtualDevice::Find(uint64_t guid_to_find)
{
if(guid == guid_to_find)
{
return this;
}
for(auto i = children.begin(); i != children.end(); i++)
{
VirtualDevice* vdev = i->Find(guid_to_find);
if(vdev != NULL)
{
return vdev;
}
}
return NULL;
}
void VirtualDevice::GetLeaves(std::list<VirtualDevice*>& leaves)
{
if(children.empty())
{
leaves.push_back(this);
}
else
{
for(auto i = children.begin(); i != children.end(); i++)
{
i->GetLeaves(leaves);
}
}
}
// Device
Device::Device()
: m_handle(NULL)
, m_start(0)
, m_size(0)
, m_label(NULL)
, m_active(NULL)
{
}
Device::~Device()
{
Close();
}
bool Device::Open(const wchar_t* path, uint32_t partition)
{
Close();
m_handle = CreateFile(path, GENERIC_READ, FILE_SHARE_READ | FILE_SHARE_WRITE | FILE_SHARE_DELETE, NULL, OPEN_EXISTING, FILE_FLAG_SEQUENTIAL_SCAN, (HANDLE)NULL);
if(m_handle == INVALID_HANDLE_VALUE)
{
m_handle = NULL;
return false;
}
if(!GetFileSizeEx(m_handle, (LARGE_INTEGER*)&m_size))
{
DISK_GEOMETRY_EX dg;
DWORD sz;
if(DeviceIoControl(m_handle, IOCTL_DISK_GET_DRIVE_GEOMETRY_EX, NULL, 0, &dg, sizeof(dg), &sz, NULL))
{
m_size = dg.DiskSize.QuadPart;
}
}
for(int i = 0; i < 2; i++, partition >>= 8)
{
uint8_t mbr[0x200];
Read(mbr, sizeof(mbr));
if(mbr[0x1fe] == 0x55 || mbr[0x1ff] == 0xaa)
{
uint8_t* ptr = &mbr[0x1be];
for(int i = 0; i < 4; i++)
{
if((partition & 0xff) == i)
{
uint64_t start = *(uint32_t*)&ptr[i * 16 + 8];
uint64_t size = *(uint32_t*)&ptr[i * 16 + 12];
if(start != 0 && size != 0)
{
m_start += start << 9;
m_size = size << 9;
}
break;
}
}
}
Seek(0);
}
m_label = new vdev_label_t();
Read(m_label, sizeof(vdev_label_t));
// TODO: verify m_label->vdev_phys.zbt.chksum
if(!m_desc.Init(m_label->vdev_phys))
{
return false;
}
for(size_t i = 0; i < sizeof(m_label->uberblock); i += m_desc.ub_size)
{
uberblock_t* ub = (uberblock_t*)&m_label->uberblock[i];
if(ub->magic == BSWAP_64(UBERBLOCK_MAGIC))
{
// TODO: be <-> le
}
if(ub->magic != UBERBLOCK_MAGIC)
{
continue;
}
if(m_active == NULL || ub->txg > m_active->txg)
{
m_active = ub;
}
}
return true;
}
void Device::Close()
{
if(m_handle != NULL)
{
CloseHandle(m_handle);
m_handle = NULL;
}
if(m_label != NULL)
{
delete m_label;
m_label = NULL;
}
m_start = 0;
m_size = 0;
m_active = NULL;
}
uint64_t Device::Seek(uint64_t pos)
{
LARGE_INTEGER li, li2;
li.QuadPart = m_start + pos;
SetFilePointerEx(m_handle, li, &li2, FILE_BEGIN);
return li.QuadPart;
}
size_t Device::Read(void* buff, uint64_t size)
{
DWORD read = 0;
ReadFile(m_handle, buff, (DWORD)size, &read, NULL);
return (size_t)read;
}
// DeviceDesc
bool DeviceDesc::Init(vdev_phys_t& vd)
{
NameValueList nvl;
nvl.Read(&vd.nvlist[4], sizeof(vd.nvlist) - 4);
try
{
guid = nvl.at("guid")->u64[0];
top_guid = nvl.at("top_guid")->u64[0];
state = nvl.at("state")->u64[0];
host.id = nvl.at("hostid")->u64[0];
host.name = nvl.at("hostname")->str[0];
pool.guid = nvl.at("pool_guid")->u64[0];
pool.name = nvl.at("name")->str[0];
txg = nvl.at("txg")->u64[0];
version = nvl.at("version")->u64[0];
top.Init(nvl.at("vdev_tree")->list);
ub_size = 1 << std::max<int>((int)top.ashift, UBERBLOCK_SHIFT);
}
catch(...)
{
return false;
}
return true;
}
}

91
zfs-win/Device.h Normal file
View File

@ -0,0 +1,91 @@
/*
* Copyright (C) 2010 Gabest
* http://code.google.com/p/zfs-win/
*
* This Program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This Program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GNU Make; see the file COPYING. If not, write to
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
* http://www.gnu.org/copyleft/gpl.html
*
*/
#pragma once
#include "zfs.h"
#include "NameValueList.h"
namespace ZFS
{
class Device;
class VirtualDevice
{
public:
Device* dev;
std::string type;
uint64_t id;
uint64_t guid;
uint64_t metaslab_array;
uint64_t metaslab_shift;
uint64_t ashift;
uint64_t asize;
std::string path;
std::string devid;
uint64_t nparity;
uint64_t whole_disk;
uint64_t is_log;
std::vector<VirtualDevice> children;
void Init(NameValueList* nvl) throw(...);
bool Read(std::vector<uint8_t>& buff, uint64_t size, uint64_t offset);
VirtualDevice* Find(uint64_t guid_to_find);
void GetLeaves(std::list<VirtualDevice*>& leaves);
};
class DeviceDesc
{
public:
uint64_t guid;
uint64_t top_guid;
uint64_t state;
struct {uint64_t id; std::string name;} host;
struct {uint64_t guid; std::string name;} pool;
uint64_t txg;
uint64_t version;
VirtualDevice top;
size_t ub_size;
bool Init(vdev_phys_t& vd);
};
class Device
{
public:
DeviceDesc m_desc;
HANDLE m_handle;
uint64_t m_start;
uint64_t m_size;
vdev_label_t* m_label;
uberblock_t* m_active;
public:
Device();
virtual ~Device();
bool Open(const wchar_t* path, uint32_t partition = 0); // partition 0x0000EEPP (PP primary, EE extended, zero based index)
void Close();
uint64_t Seek(uint64_t pos);
size_t Read(void* buff, uint64_t size);
};
}

247
zfs-win/Hash.cpp Normal file
View File

@ -0,0 +1,247 @@
/*
* 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 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
/*
* Fletcher Checksums
* ------------------
*
* ZFS's 2nd and 4th order Fletcher checksums are defined by the following
* recurrence relations:
*
* a = a + f
* i i-1 i-1
*
* b = b + a
* i i-1 i
*
* c = c + b (fletcher-4 only)
* i i-1 i
*
* d = d + c (fletcher-4 only)
* i i-1 i
*
* Where
* a_0 = b_0 = c_0 = d_0 = 0
* and
* f_0 .. f_(n-1) are the input data.
*
* Using standard techniques, these translate into the following series:
*
* __n_ __n_
* \ | \ |
* a = > f b = > i * f
* n /___| n - i n /___| n - i
* i = 1 i = 1
*
*
* __n_ __n_
* \ | i*(i+1) \ | i*(i+1)*(i+2)
* c = > ------- f d = > ------------- f
* n /___| 2 n - i n /___| 6 n - i
* i = 1 i = 1
*
* For fletcher-2, the f_is are 64-bit, and [ab]_i are 64-bit accumulators.
* Since the additions are done mod (2^64), errors in the high bits may not
* be noticed. For this reason, fletcher-2 is deprecated.
*
* For fletcher-4, the f_is are 32-bit, and [abcd]_i are 64-bit accumulators.
* A conservative estimate of how big the buffer can get before we overflow
* can be estimated using f_i = 0xffffffff for all i:
*
* % bc
* f=2^32-1;d=0; for (i = 1; d<2^64; i++) { d += f*i*(i+1)*(i+2)/6 }; (i-1)*4
* 2264
* quit
* %
*
* So blocks of up to 2k will not overflow. Our largest block size is
* 128k, which has 32k 4-byte words, so we can compute the largest possible
* accumulators, then divide by 2^64 to figure the max amount of overflow:
*
* % bc
* a=b=c=d=0; f=2^32-1; for (i=1; i<=32*1024; i++) { a+=f; b+=a; c+=b; d+=c }
* a/2^64;b/2^64;c/2^64;d/2^64
* 0
* 0
* 1365
* 11186858
* quit
* %
*
* So a and b cannot overflow. To make sure each bit of input has some
* effect on the contents of c and d, we can look at what the factors of
* the coefficients in the equations for c_n and d_n are. The number of 2s
* in the factors determines the lowest set bit in the multiplier. Running
* through the cases for n*(n+1)/2 reveals that the highest power of 2 is
* 2^14, and for n*(n+1)*(n+2)/6 it is 2^15. So while some data may overflow
* the 64-bit accumulators, every bit of every f_i effects every accumulator,
* even for 128k blocks.
*
* If we wanted to make a stronger version of fletcher4 (fletcher4c?),
* we could do our calculations mod (2^32 - 1) by adding in the carries
* periodically, and store the number of carries in the top 32-bits.
*
* --------------------
* Checksum Performance
* --------------------
*
* There are two interesting components to checksum performance: cached and
* uncached performance. With cached data, fletcher-2 is about four times
* faster than fletcher-4. With uncached data, the performance difference is
* negligible, since the cost of a cache fill dominates the processing time.
* Even though fletcher-4 is slower than fletcher-2, it is still a pretty
* efficient pass over the data.
*
* In normal operation, the data which is being checksummed is in a buffer
* which has been filled either by:
*
* 1. a compression step, which will be mostly cached, or
* 2. a bcopy() or copyin(), which will be uncached (because the
* copy is cache-bypassing).
*
* For both cached and uncached data, both fletcher checksums are much faster
* than sha-256, and slower than 'off', which doesn't touch the data at all.
*/
#include "stdafx.h"
#include "Hash.h"
void fletcher_2_native(const void* buf, uint64_t size, cksum_t* zcp)
{
const uint64_t* ip = (const uint64_t*)buf;
const uint64_t* ipend = ip + (size / sizeof(uint64_t));
uint64_t a0, b0, a1, b1;
for(a0 = b0 = a1 = b1 = 0; ip < ipend; ip += 2)
{
a0 += ip[0];
a1 += ip[1];
b0 += a0;
b1 += a1;
}
zcp->set(a0, a1, b0, b1);
}
void fletcher_2_byteswap(const void* buf, uint64_t size, cksum_t* zcp)
{
const uint64_t* ip = (const uint64_t*)buf;
const uint64_t* ipend = ip + (size / sizeof(uint64_t));
uint64_t a0, b0, a1, b1;
for(a0 = b0 = a1 = b1 = 0; ip < ipend; ip += 2)
{
a0 += BSWAP_64(ip[0]);
a1 += BSWAP_64(ip[1]);
b0 += a0;
b1 += a1;
}
zcp->set(a0, a1, b0, b1);
}
void fletcher_4_native(const void* buf, uint64_t size, cksum_t* zcp)
{
const uint32_t* ip = (const uint32_t*)buf;
const uint32_t* ipend = ip + (size / sizeof(uint32_t));
uint64_t a, b, c, d;
for(a = b = c = d = 0; ip < ipend; ip++)
{
a += ip[0];
b += a;
c += b;
d += c;
}
zcp->set(a, b, c, d);
}
void fletcher_4_byteswap(const void* buf, uint64_t size, cksum_t* zcp)
{
const uint32_t* ip = (const uint32_t*)buf;
const uint32_t* ipend = ip + (size / sizeof(uint32_t));
uint64_t a, b, c, d;
for(a = b = c = d = 0; ip < ipend; ip++)
{
a += BSWAP_32(ip[0]);
b += a;
c += b;
d += c;
}
zcp->set(a, b, c, d);
}
void fletcher_4_incremental_native(const void* buf, uint64_t size, cksum_t* zcp)
{
const uint32_t* ip = (const uint32_t*)buf;
const uint32_t* ipend = ip + (size / sizeof(uint32_t));
uint64_t a, b, c, d;
a = zcp->word[0];
b = zcp->word[1];
c = zcp->word[2];
d = zcp->word[3];
for(; ip < ipend; ip++)
{
a += ip[0];
b += a;
c += b;
d += c;
}
zcp->set(a, b, c, d);
}
void fletcher_4_incremental_byteswap(const void* buf, uint64_t size, cksum_t* zcp)
{
const uint32_t* ip = (const uint32_t*)buf;
const uint32_t* ipend = ip + (size / sizeof(uint32_t));
uint64_t a, b, c, d;
a = zcp->word[0];
b = zcp->word[1];
c = zcp->word[2];
d = zcp->word[3];
for(; ip < ipend; ip++)
{
a += BSWAP_32(ip[0]);
b += a;
c += b;
d += c;
}
zcp->set(a, b, c, d);
}

138
zfs-win/Hash.h Normal file
View File

@ -0,0 +1,138 @@
/*
* 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 2009 Sun Microsystems, Inc. All rights reserved.
* Use is subject to license terms.
*/
/*
* Fletcher Checksums
* ------------------
*
* ZFS's 2nd and 4th order Fletcher checksums are defined by the following
* recurrence relations:
*
* a = a + f
* i i-1 i-1
*
* b = b + a
* i i-1 i
*
* c = c + b (fletcher-4 only)
* i i-1 i
*
* d = d + c (fletcher-4 only)
* i i-1 i
*
* Where
* a_0 = b_0 = c_0 = d_0 = 0
* and
* f_0 .. f_(n-1) are the input data.
*
* Using standard techniques, these translate into the following series:
*
* __n_ __n_
* \ | \ |
* a = > f b = > i * f
* n /___| n - i n /___| n - i
* i = 1 i = 1
*
*
* __n_ __n_
* \ | i*(i+1) \ | i*(i+1)*(i+2)
* c = > ------- f d = > ------------- f
* n /___| 2 n - i n /___| 6 n - i
* i = 1 i = 1
*
* For fletcher-2, the f_is are 64-bit, and [ab]_i are 64-bit accumulators.
* Since the additions are done mod (2^64), errors in the high bits may not
* be noticed. For this reason, fletcher-2 is deprecated.
*
* For fletcher-4, the f_is are 32-bit, and [abcd]_i are 64-bit accumulators.
* A conservative estimate of how big the buffer can get before we overflow
* can be estimated using f_i = 0xffffffff for all i:
*
* % bc
* f=2^32-1;d=0; for (i = 1; d<2^64; i++) { d += f*i*(i+1)*(i+2)/6 }; (i-1)*4
* 2264
* quit
* %
*
* So blocks of up to 2k will not overflow. Our largest block size is
* 128k, which has 32k 4-byte words, so we can compute the largest possible
* accumulators, then divide by 2^64 to figure the max amount of overflow:
*
* % bc
* a=b=c=d=0; f=2^32-1; for (i=1; i<=32*1024; i++) { a+=f; b+=a; c+=b; d+=c }
* a/2^64;b/2^64;c/2^64;d/2^64
* 0
* 0
* 1365
* 11186858
* quit
* %
*
* So a and b cannot overflow. To make sure each bit of input has some
* effect on the contents of c and d, we can look at what the factors of
* the coefficients in the equations for c_n and d_n are. The number of 2s
* in the factors determines the lowest set bit in the multiplier. Running
* through the cases for n*(n+1)/2 reveals that the highest power of 2 is
* 2^14, and for n*(n+1)*(n+2)/6 it is 2^15. So while some data may overflow
* the 64-bit accumulators, every bit of every f_i effects every accumulator,
* even for 128k blocks.
*
* If we wanted to make a stronger version of fletcher4 (fletcher4c?),
* we could do our calculations mod (2^32 - 1) by adding in the carries
* periodically, and store the number of carries in the top 32-bits.
*
* --------------------
* Checksum Performance
* --------------------
*
* There are two interesting components to checksum performance: cached and
* uncached performance. With cached data, fletcher-2 is about four times
* faster than fletcher-4. With uncached data, the performance difference is
* negligible, since the cost of a cache fill dominates the processing time.
* Even though fletcher-4 is slower than fletcher-2, it is still a pretty
* efficient pass over the data.
*
* In normal operation, the data which is being checksummed is in a buffer
* which has been filled either by:
*
* 1. a compression step, which will be mostly cached, or
* 2. a bcopy() or copyin(), which will be uncached (because the
* copy is cache-bypassing).
*
* For both cached and uncached data, both fletcher checksums are much faster
* than sha-256, and slower than 'off', which doesn't touch the data at all.
*/
#include "stdafx.h"
#include "zfs.h"
extern void fletcher_2_native(const void* buf, uint64_t size, cksum_t* zcp);
extern void fletcher_2_byteswap(const void* buf, uint64_t size, cksum_t* zcp);
extern void fletcher_4_native(const void* buf, uint64_t size, cksum_t* zcp);
extern void fletcher_4_byteswap(const void* buf, uint64_t size, cksum_t* zcp);
extern void fletcher_4_incremental_native(const void* buf, uint64_t size, cksum_t* zcp);
extern void fletcher_4_incremental_byteswap(const void* buf, uint64_t size, cksum_t* zcp);
// TODO: sha256

249
zfs-win/NameValueList.cpp Normal file
View File

@ -0,0 +1,249 @@
/*
* Copyright (C) 2010 Gabest
* http://code.google.com/p/zfs-win/
*
* This Program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This Program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GNU Make; see the file COPYING. If not, write to
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
* http://www.gnu.org/copyleft/gpl.html
*
*/
#include "stdafx.h"
#include "NameValueList.h"
namespace ZFS
{
NameValuePair::NameValuePair()
{
u8 = NULL;
}
NameValuePair::~NameValuePair()
{
if(u8 != NULL)
{
switch(type)
{
case TYPE_INT8:
case TYPE_INT8_ARRAY:
case TYPE_UINT8:
case TYPE_UINT8_ARRAY:
delete [] u8;
break;
case TYPE_INT16:
case TYPE_INT16_ARRAY:
case TYPE_UINT16:
case TYPE_UINT16_ARRAY:
delete [] u16;
break;
case TYPE_INT32:
case TYPE_INT32_ARRAY:
case TYPE_UINT32:
case TYPE_UINT32_ARRAY:
delete [] u32;
break;
case TYPE_INT64:
case TYPE_INT64_ARRAY:
case TYPE_UINT64:
case TYPE_UINT64_ARRAY:
delete [] u64;
break;
case TYPE_STRING:
case TYPE_STRING_ARRAY:
delete [] str;
break;
case TYPE_NVLIST:
case TYPE_NVLIST_ARRAY:
delete [] list;
break;
default:
break;
}
u8 = NULL;
}
}
NameValueList::NameValueList()
{
}
NameValueList::~NameValueList()
{
for(auto i = begin(); i != end(); i++)
{
delete i->second;
}
}
const uint8_t* NameValueList::Read(const uint8_t* ptr, size_t size)
{
const uint8_t* ptr_end = ptr + size;
uint32_t version = ReadU32(ptr);
uint32_t flags = ReadU32(ptr);
while(ptr < ptr_end)
{
const uint8_t* ptr_start = ptr;
uint32_t esize = ReadU32(ptr);
uint32_t dsize = ReadU32(ptr);
if(esize == 0 && dsize == 0) break;
NameValuePair* pair = new NameValuePair();
std::string name = ReadString(ptr);
pair->type = (NameValueType)ReadU32(ptr);
pair->count = ReadU32(ptr);
if(pair->count > 0)
{
switch(pair->type)
{
case TYPE_BOOLEAN:
case TYPE_BOOLEAN_ARRAY: // ???
break;
case TYPE_BYTE:
case TYPE_BYTE_ARRAY: // ???
break;
case TYPE_INT8:
case TYPE_INT8_ARRAY:
case TYPE_UINT8:
case TYPE_UINT8_ARRAY:
pair->u8 = new uint8_t[pair->count];
for(uint32_t i = 0; i < pair->count; i++)
pair->u8[i] = ReadU8(ptr);
break;
case TYPE_INT16:
case TYPE_INT16_ARRAY:
case TYPE_UINT16:
case TYPE_UINT16_ARRAY:
pair->u16 = new uint16_t[pair->count];
for(uint32_t i = 0; i < pair->count; i++)
pair->u16[i] = ReadU16(ptr);
break;
case TYPE_INT32:
case TYPE_INT32_ARRAY:
case TYPE_UINT32:
case TYPE_UINT32_ARRAY:
pair->u32 = new uint32_t[pair->count];
for(uint32_t i = 0; i < pair->count; i++)
pair->u32[i] = ReadU32(ptr);
break;
case TYPE_INT64:
case TYPE_INT64_ARRAY:
case TYPE_UINT64:
case TYPE_UINT64_ARRAY:
pair->u64 = new uint64_t[pair->count];
for(uint32_t i = 0; i < pair->count; i++)
pair->u64[i] = ReadU64(ptr);
break;
case TYPE_STRING:
case TYPE_STRING_ARRAY:
pair->str = new std::string[pair->count];
for(uint32_t i = 0; i < pair->count; i++)
pair->str[i] = ReadString(ptr);
break;
case TYPE_NVLIST:
case TYPE_NVLIST_ARRAY:
pair->list = new NameValueList[pair->count];
for(uint32_t i = 0; i < pair->count; i++)
ptr = pair->list[i].Read(ptr, ptr_start + esize - ptr);
break;
case TYPE_BOOLEAN_VALUE: // ???
ASSERT(0);
break;
case TYPE_HRTIME: // ???
ASSERT(0);
break;
case TYPE_DOUBLE: // ???
ASSERT(0);
break;
case TYPE_UNKNOWN:
default:
ASSERT(0);
break;
}
auto i = find(name);
if(i != end())
{
delete i->second;
erase(i);
}
(*this)[name] = pair;
}
ptr = ptr_start + esize;
}
return ptr;
}
uint8_t NameValueList::ReadU8(const uint8_t*& ptr)
{
uint8_t v = ptr[0];
ptr += 1;
return v;
}
uint16_t NameValueList::ReadU16(const uint8_t*& ptr)
{
uint16_t v = (ptr[0] << 8) | ptr[1];
ptr += 2;
return v;
}
uint32_t NameValueList::ReadU32(const uint8_t*& ptr)
{
uint32_t v = (ptr[0] << 24) | (ptr[1] << 16) | (ptr[2] << 8) | (ptr[3] << 0);
ptr += 4;
return v;
}
uint64_t NameValueList::ReadU64(const uint8_t*& ptr)
{
uint64_t v;
((uint32_t*)&v)[1] = (ptr[0] << 24) | (ptr[1] << 16) | (ptr[2] << 8) | ptr[3];
((uint32_t*)&v)[0] = (ptr[4] << 24) | (ptr[5] << 16) | (ptr[6] << 8) | ptr[7];
ptr += 8;
return v;
}
std::string NameValueList::ReadString(const uint8_t*& ptr)
{
uint32_t size = ReadU32(ptr);
std::string s((const char*)ptr, size);
ptr += (size + 3) & ~3;
return s;
}
}

98
zfs-win/NameValueList.h Normal file
View File

@ -0,0 +1,98 @@
/*
* Copyright (C) 2010 Gabest
* http://code.google.com/p/zfs-win/
*
* This Program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This Program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GNU Make; see the file COPYING. If not, write to
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
* http://www.gnu.org/copyleft/gpl.html
*
*/
#pragma once
namespace ZFS
{
enum NameValueType
{
TYPE_UNKNOWN = 0,
TYPE_BOOLEAN,
TYPE_BYTE,
TYPE_INT16,
TYPE_UINT16,
TYPE_INT32,
TYPE_UINT32,
TYPE_INT64,
TYPE_UINT64,
TYPE_STRING,
TYPE_BYTE_ARRAY,
TYPE_INT16_ARRAY,
TYPE_UINT16_ARRAY,
TYPE_INT32_ARRAY,
TYPE_UINT32_ARRAY,
TYPE_INT64_ARRAY,
TYPE_UINT64_ARRAY,
TYPE_STRING_ARRAY,
TYPE_HRTIME,
TYPE_NVLIST,
TYPE_NVLIST_ARRAY,
TYPE_BOOLEAN_VALUE,
TYPE_INT8,
TYPE_UINT8,
TYPE_BOOLEAN_ARRAY,
TYPE_INT8_ARRAY,
TYPE_UINT8_ARRAY,
TYPE_DOUBLE
};
class NameValueList;
class NameValuePair
{
public:
NameValueType type;
uint32_t count;
union
{
int8_t* i8;
uint8_t* u8;
int16_t* i16;
uint16_t* u16;
int32_t* i32;
uint32_t* u32;
int64_t* i64;
uint64_t* u64;
std::string* str;
NameValueList* list;
};
NameValuePair();
virtual ~NameValuePair();
};
class NameValueList : public std::map<std::string, NameValuePair*>
{
uint8_t ReadU8(const uint8_t*& ptr);
uint16_t ReadU16(const uint8_t*& ptr);
uint32_t ReadU32(const uint8_t*& ptr);
uint64_t ReadU64(const uint8_t*& ptr);
std::string ReadString(const uint8_t*& ptr);
public:
NameValueList();
virtual ~NameValueList();
const uint8_t* Read(const uint8_t* ptr, size_t size);
};
}

132
zfs-win/Pool.cpp Normal file
View File

@ -0,0 +1,132 @@
/*
* Copyright (C) 2010 Gabest
* http://code.google.com/p/zfs-win/
*
* This Program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This Program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GNU Make; see the file COPYING. If not, write to
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
* http://www.gnu.org/copyleft/gpl.html
*
*/
#include "stdafx.h"
#include "Pool.h"
#include "BlockReader.h"
namespace ZFS
{
Pool::Pool()
: m_guid(0)
{
}
Pool::~Pool()
{
Close();
}
bool Pool::Open(const char* name, const std::list<std::wstring>& paths)
{
Close();
m_name = name;
for(auto i = paths.begin(); i != paths.end(); i++)
{
Device* dev = new Device();
if(!dev->Open(i->c_str()))
{
return false;
}
if(m_name == dev->m_desc.pool.name && (m_guid == 0 || m_guid == dev->m_desc.pool.guid))
{
m_guid = dev->m_desc.pool.guid;
m_devs.push_back(dev);
auto cmp_tree = [&] (const VirtualDevice* vdev) -> bool {return vdev->guid == dev->m_desc.top.guid;};
if(std::find_if(m_vdevs.begin(), m_vdevs.end(), cmp_tree) == m_vdevs.end())
{
m_vdevs.push_back(&dev->m_desc.top);
}
}
else
{
delete dev;
}
}
if(m_devs.empty())
{
return false;
}
for(auto i = m_vdevs.begin(); i != m_vdevs.end(); i++)
{
std::list<VirtualDevice*> leaves;
VirtualDevice* vdev = *i;
vdev->GetLeaves(leaves);
for(auto j = leaves.begin(); j != leaves.end(); j++)
{
VirtualDevice* leaf = *j;
for(auto k = m_devs.begin(); k != m_devs.end(); k++)
{
Device* dev = *k;
if(leaf->guid == dev->m_desc.guid)
{
ASSERT(vdev->guid == dev->m_desc.top_guid);
leaf->dev = dev;
break;
}
}
if(leaf->dev == NULL)
{
return false;
}
}
}
return true;
}
void Pool::Close()
{
for(auto i = m_devs.begin(); i != m_devs.end(); i++)
{
delete *i;
}
m_guid = 0;
m_name.clear();
m_devs.clear();
m_vdevs.clear();
}
bool Pool::Read(std::vector<uint8_t>& buff, blkptr_t* bp, size_t count)
{
BlockReader r(this, bp, count);
return r.ReadToEnd(buff);
}
}

46
zfs-win/Pool.h Normal file
View File

@ -0,0 +1,46 @@
/*
* Copyright (C) 2010 Gabest
* http://code.google.com/p/zfs-win/
*
* This Program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This Program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GNU Make; see the file COPYING. If not, write to
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
* http://www.gnu.org/copyleft/gpl.html
*
*/
#pragma once
#include "zfs.h"
#include "Device.h"
namespace ZFS
{
class Pool
{
public:
uint64_t m_guid;
std::string m_name;
std::vector<Device*> m_devs;
std::vector<VirtualDevice*> m_vdevs;
public:
Pool();
virtual ~Pool();
bool Open(const char* name, const std::list<std::wstring>& paths);
void Close();
bool Read(std::vector<uint8_t>& buff, blkptr_t* bp, size_t count);
};
}

182
zfs-win/ZapObject.cpp Normal file
View File

@ -0,0 +1,182 @@
/*
* Copyright (C) 2010 Gabest
* http://code.google.com/p/zfs-win/
*
* This Program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This Program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GNU Make; see the file COPYING. If not, write to
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
* http://www.gnu.org/copyleft/gpl.html
*
*/
#include "StdAfx.h"
#include "ZapObject.h"
namespace ZFS
{
ZapObject::ZapObject(std::vector<uint8_t>& buff)
{
if(buff.size() >= sizeof(uint64_t))
{
uint64_t* ptr = (uint64_t*)buff.data();
if(*ptr == ZBT_MICRO) ParseMicro(buff);
else if(*ptr == ZBT_HEADER) ParseFat(buff);
}
}
ZapObject::~ZapObject()
{
for(auto i = begin(); i != end(); i++)
{
delete i->second;
}
}
bool ZapObject::Lookup(const char* name, uint64_t& value)
{
auto i = find(name);
if(i != end())
{
if(i->second->size() == 8)
{
value = BSWAP_64(*(uint64_t*)i->second->data()); // fat zap big endian???
return true;
}
}
return false;
}
bool ZapObject::Lookup(const char* name, std::string& value)
{
auto i = find(name);
if(i != end())
{
value = std::string((char*)i->second->data(), i->second->size());
return true;
}
return false;
}
void ZapObject::ParseMicro(std::vector<uint8_t>& buff)
{
mzap_phys_t* mzap = (mzap_phys_t*)buff.data();
for(size_t i = 0, n = buff.size() / MZAP_ENT_LEN - 1; i < n; i++)
{
std::string name = mzap->chunk[i].name;
if(name.empty()) continue;
auto j = find(name);
if(j != end())
{
delete j->second;
erase(j);
}
std::vector<uint8_t>* value = new std::vector<uint8_t>(sizeof(uint64_t));
uint64_t tmp = BSWAP_64(mzap->chunk[i].value); // make the same as fat zap
memcpy(value->data(), &tmp, sizeof(uint64_t));
(*this)[name] = value;
}
}
void ZapObject::ParseFat(std::vector<uint8_t>& buff)
{
size_t half_size = buff.size() / 2; // first half wasted ???
zap_phys_t* zap = (zap_phys_t*)buff.data();
zap_leaf_phys_t* leaf = (zap_leaf_phys_t*)(buff.data() + half_size);
zap_leaf_entry_t* e = (zap_leaf_entry_t*)(uint8_t*)&leaf->hash[half_size / 32];
zap_leaf_entry_t* e_end = (zap_leaf_entry_t*)(buff.data() + buff.size());
for(size_t i = 0, n = e_end - e; i < n; i++)
{
if(e[i].type != ZAP_CHUNK_ENTRY)
{
continue;
}
std::vector<uint8_t> name(e[i].name_numints);
if(!ParseArray(name, e, e[i].name_chunk) || name.empty())
{
continue;
}
std::vector<uint8_t>* value = new std::vector<uint8_t>(e[i].value_numints * e[i].value_intlen);
if(!ParseArray(*value, e, e[i].value_chunk))
{
delete value;
continue;
}
std::string s((char*)name.data(), name.size() - 1);
auto j = find(s);
if(j != end())
{
delete j->second;
erase(j);
}
(*this)[s] = value;
}
}
bool ZapObject::ParseArray(std::vector<uint8_t>& buff, zap_leaf_entry_t* e, uint16_t index)
{
uint8_t* ptr = buff.data();
size_t size = buff.size();
while(index != 0xffff)
{
zap_leaf_array_t* l = (zap_leaf_array_t*)&e[index];
if(l->type != ZAP_CHUNK_ARRAY)
{
ASSERT(0);
break;
}
size_t n = std::min<size_t>(size, ZAP_LEAF_ARRAY_BYTES);
memcpy(ptr, l->buff, n);
ptr += n;
size -= n;
index = l->next;
}
return size == 0;
}
}

41
zfs-win/ZapObject.h Normal file
View File

@ -0,0 +1,41 @@
/*
* Copyright (C) 2010 Gabest
* http://code.google.com/p/zfs-win/
*
* This Program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This Program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GNU Make; see the file COPYING. If not, write to
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
* http://www.gnu.org/copyleft/gpl.html
*
*/
#pragma once
#include "zfs.h"
namespace ZFS
{
class ZapObject : public std::map<std::string, std::vector<uint8_t>*>
{
void ParseMicro(std::vector<uint8_t>& buff);
void ParseFat(std::vector<uint8_t>& buff);
bool ParseArray(std::vector<uint8_t>& buff, zap_leaf_entry_t* e, uint16_t index);
public:
ZapObject(std::vector<uint8_t>& buff);
virtual ~ZapObject();
bool Lookup(const char* name, uint64_t& value);
bool Lookup(const char* name, std::string& value);
};
}

210
zfs-win/main.cpp Normal file
View File

@ -0,0 +1,210 @@
/*
* Copyright (C) 2010 Gabest
* http://code.google.com/p/zfs-win/
*
* This Program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This Program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GNU Make; see the file COPYING. If not, write to
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
* http://www.gnu.org/copyleft/gpl.html
*
*/
#include "stdafx.h"
#include "Pool.h"
#include "Device.h"
#include "ZapObject.h"
int _tmain(int argc, _TCHAR* argv[])
{
// this is just a test, recreating the steps of "ZFS On-Disk Data Walk (Or: Where's My Data)" (google for it)
std::list<std::wstring> paths;
/*
for(int i = 2; i < argc; i++)
{
paths.push_back(argv[i]);
}
*/
const char* name = "mpool";
paths.push_back(L"D:\\Virtual Machines\\ZFSVM\\ZFSVM1-flat.vmdk");
/*
paths.push_back(L"D:\\Virtual Machines\\ZFSVM\\ZFSVM2-flat.vmdk");
paths.push_back(L"D:\\Virtual Machines\\ZFSVM\\ZFSVM3-flat.vmdk");
paths.push_back(L"D:\\Virtual Machines\\ZFSVM\\ZFSVM4-flat.vmdk");
paths.push_back(L"D:\\Virtual Machines\\ZFSVM\\ZFSVM5-flat.vmdk");
paths.push_back(L"D:\\Virtual Machines\\ZFSVM\\ZFSVM6-flat.vmdk");
paths.push_back(L"D:\\Virtual Machines\\ZFSVM\\ZFSVM7-flat.vmdk");
paths.push_back(L"D:\\Virtual Machines\\ZFSVM\\ZFSVM8-flat.vmdk");
*/
/*
const char* name = "share";
paths.push_back(L"\\\\.\\PhysicalDrive1");
paths.push_back(L"\\\\.\\PhysicalDrive2");
paths.push_back(L"\\\\.\\PhysicalDrive3");
paths.push_back(L"\\\\.\\PhysicalDrive4");
*/
/*
const char* name = "rpool";
paths.push_back(L"D:\\Virtual Machines\\OpenSolaris\\OpenSolaris-flat.vmdk");
*/
ZFS::Pool p;
if(!p.Open(name, paths))
{
return -1;
}
ZFS::Device* dev = p.m_devs.front();
if(dev->m_active->rootbp.type == DMU_OT_OBJSET)
{
std::vector<uint8_t> buff;
if(p.Read(buff, &dev->m_active->rootbp, 1))
{
objset_phys_t* os = (objset_phys_t*)buff.data();
if(os->type == DMU_OST_META && os->meta_dnode.type == DMU_OT_DNODE)
{
std::vector<uint8_t> buff;
if(p.Read(buff, os->meta_dnode.blkptr, os->meta_dnode.nblkptr))
{
dnode_phys_t* dn = (dnode_phys_t*)buff.data();
size_t count = buff.size() / sizeof(dnode_phys_t);
ASSERT(count > 2);
dnode_phys_t* root_dataset = NULL;
ASSERT(dn[1].type == DMU_OT_OBJECT_DIRECTORY);
if(dn[1].type == DMU_OT_OBJECT_DIRECTORY)
{
std::vector<uint8_t> buff;
if(p.Read(buff, dn[1].blkptr, dn[1].nblkptr))
{
ZFS::ZapObject zap(buff);
uint64_t index;
if(zap.Lookup("root_dataset", index))
{
if(index < count && dn[index].type == DMU_OT_DSL_DIR)
{
root_dataset = &dn[index];
}
}
}
}
dnode_phys_t* head_dataset = NULL;
if(root_dataset != NULL)
{
dsl_dir_phys_t* dir = (dsl_dir_phys_t*)root_dataset->bonus;
size_t index = (size_t)dir->head_dataset_obj;
if(index < count && dn[index].type == DMU_OT_DSL_DATASET)
{
head_dataset = &dn[index];
}
}
if(head_dataset != NULL)
{
dsl_dataset_phys_t* ds = (dsl_dataset_phys_t*)head_dataset->bonus;
if(ds->bp.type == DMU_OT_OBJSET)
{
std::vector<uint8_t> buff;
if(p.Read(buff, &ds->bp, 1))
{
objset_phys_t* os = (objset_phys_t*)buff.data();
if(os->type == DMU_OST_ZFS && os->meta_dnode.type == DMU_OT_DNODE)
{
std::vector<uint8_t> buff;
if(p.Read(buff, os->meta_dnode.blkptr, os->meta_dnode.nblkptr))
{
dnode_phys_t* dn = (dnode_phys_t*)buff.data();
size_t count = buff.size() / sizeof(dnode_phys_t);
ASSERT(count > 2);
dnode_phys_t* root = NULL;
ASSERT(dn[1].type == DMU_OT_MASTER_NODE);
if(dn[1].type == DMU_OT_MASTER_NODE)
{
std::vector<uint8_t> buff;
if(p.Read(buff, dn[1].blkptr, dn[1].nblkptr))
{
ZFS::ZapObject zap(buff);
uint64_t index;
if(zap.Lookup("ROOT", index)) // NOTE: the ROOT dataset may not contain too many files, don't be surprised
{
if(index < count && dn[index].type == DMU_OT_DIRECTORY_CONTENTS)
{
root = &dn[index];
}
else
{
ASSERT(0);
}
}
}
}
if(root != NULL)
{
znode_phys_t* node = (znode_phys_t*)root->bonus;
std::vector<uint8_t> buff;
if(p.Read(buff, root->blkptr, root->nblkptr))
{
mzap_phys_t* mzap = (mzap_phys_t*)buff.data();
// finally, arrived at the root directory
int i = 0;
}
}
}
}
}
}
}
}
}
}
}
return 0;
}

29
zfs-win/stdafx.cpp Normal file
View File

@ -0,0 +1,29 @@
/*
* Copyright (C) 2010 Gabest
* http://code.google.com/p/zfs-win/
*
* This Program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This Program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GNU Make; see the file COPYING. If not, write to
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
* http://www.gnu.org/copyleft/gpl.html
*
*/
// stdafx.cpp : source file that includes just the standard includes
// zfs-win.pch will be the pre-compiled header
// stdafx.obj will contain the pre-compiled type information
#include "stdafx.h"
// TODO: reference any additional headers you need in STDAFX.H
// and not in this file

55
zfs-win/stdafx.h Normal file
View File

@ -0,0 +1,55 @@
/*
* Copyright (C) 2010 Gabest
* http://code.google.com/p/zfs-win/
*
* This Program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This Program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GNU Make; see the file COPYING. If not, write to
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
* http://www.gnu.org/copyleft/gpl.html
*
*/
// stdafx.h : include file for standard system include files,
// or project specific include files that are used frequently, but
// are changed infrequently
//
#pragma once
#include "targetver.h"
#include <windows.h>
#include <stdio.h>
#include <stdint.h>
#include <tchar.h>
#include <vector>
#include <list>
#include <map>
#include <set>
#include <queue>
#include <stack>
#include <string>
#include <memory>
#include <algorithm>
#ifndef ASSERT
#if defined(_DEBUG) && defined(_MSC_VER)
#include <assert.h>
#define ASSERT assert
#else
#define ASSERT(exp) ((void)0)
#endif
#endif
// TODO: reference additional headers your program requires here

29
zfs-win/targetver.h Normal file
View File

@ -0,0 +1,29 @@
/*
* Copyright (C) 2010 Gabest
* http://code.google.com/p/zfs-win/
*
* This Program is free software; you can redistribute it and/or modify
* it under the terms of the GNU General Public License as published by
* the Free Software Foundation; either version 2, or (at your option)
* any later version.
*
* This Program is distributed in the hope that it will be useful,
* but WITHOUT ANY WARRANTY; without even the implied warranty of
* MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
* GNU General Public License for more details.
*
* You should have received a copy of the GNU General Public License
* along with GNU Make; see the file COPYING. If not, write to
* the Free Software Foundation, 675 Mass Ave, Cambridge, MA 02139, USA.
* http://www.gnu.org/copyleft/gpl.html
*
*/
#pragma once
// Including SDKDDKVer.h defines the highest available Windows platform.
// If you wish to build your application for a previous Windows platform, include WinSDKVer.h and
// set the _WIN32_WINNT macro to the platform you wish to support before including SDKDDKVer.h.
#include <SDKDDKVer.h>

93
zfs-win/zfs-win.vcxproj Normal file
View File

@ -0,0 +1,93 @@
<?xml version="1.0" encoding="utf-8"?>
<Project DefaultTargets="Build" ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup Label="ProjectConfigurations">
<ProjectConfiguration Include="Debug|Win32">
<Configuration>Debug</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
<ProjectConfiguration Include="Release|Win32">
<Configuration>Release</Configuration>
<Platform>Win32</Platform>
</ProjectConfiguration>
</ItemGroup>
<PropertyGroup Label="Globals">
<ProjectGuid>{4A7767E8-F121-4CA9-9147-D3B29A0F831E}</ProjectGuid>
<Keyword>Win32Proj</Keyword>
<RootNamespace>zfs-win</RootNamespace>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.Default.props" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>true</UseDebugLibraries>
<CharacterSet>Unicode</CharacterSet>
</PropertyGroup>
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" Label="Configuration">
<ConfigurationType>Application</ConfigurationType>
<UseDebugLibraries>false</UseDebugLibraries>
<CharacterSet>Unicode</CharacterSet>
<WholeProgramOptimization>true</WholeProgramOptimization>
</PropertyGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.props" />
<ImportGroup Label="ExtensionSettings">
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="..\common.props" />
<Import Project="..\debug.props" />
</ImportGroup>
<ImportGroup Label="PropertySheets" Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<Import Project="$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props" Condition="exists('$(UserRootDir)\Microsoft.Cpp.$(Platform).user.props')" Label="LocalAppDataPlatform" />
<Import Project="..\common.props" />
<Import Project="..\release.props" />
</ImportGroup>
<PropertyGroup Label="UserMacros" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'" />
<PropertyGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'" />
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">
<ClCompile>
<PrecompiledHeader>Use</PrecompiledHeader>
<PreprocessorDefinitions>_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
</Link>
</ItemDefinitionGroup>
<ItemDefinitionGroup Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">
<ClCompile>
<PrecompiledHeader>Use</PrecompiledHeader>
<PreprocessorDefinitions>_CONSOLE;%(PreprocessorDefinitions)</PreprocessorDefinitions>
</ClCompile>
<Link>
<SubSystem>Console</SubSystem>
</Link>
</ItemDefinitionGroup>
<ItemGroup>
<ClInclude Include="BlockReader.h" />
<ClInclude Include="Device.h" />
<ClInclude Include="Compress.h" />
<ClInclude Include="Hash.h" />
<ClInclude Include="NameValueList.h" />
<ClInclude Include="stdafx.h" />
<ClInclude Include="targetver.h" />
<ClInclude Include="Pool.h" />
<ClInclude Include="ZapObject.h" />
<ClInclude Include="zfs.h" />
</ItemGroup>
<ItemGroup>
<ClCompile Include="BlockReader.cpp" />
<ClCompile Include="Device.cpp" />
<ClCompile Include="Compress.cpp" />
<ClCompile Include="NameValueList.cpp" />
<ClCompile Include="stdafx.cpp">
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Debug|Win32'">Create</PrecompiledHeader>
<PrecompiledHeader Condition="'$(Configuration)|$(Platform)'=='Release|Win32'">Create</PrecompiledHeader>
</ClCompile>
<ClCompile Include="Pool.cpp" />
<ClCompile Include="main.cpp" />
<ClCompile Include="Hash.cpp" />
<ClCompile Include="ZapObject.cpp" />
</ItemGroup>
<Import Project="$(VCTargetsPath)\Microsoft.Cpp.targets" />
<ImportGroup Label="ExtensionTargets">
</ImportGroup>
</Project>

View File

@ -0,0 +1,78 @@
<?xml version="1.0" encoding="utf-8"?>
<Project ToolsVersion="4.0" xmlns="http://schemas.microsoft.com/developer/msbuild/2003">
<ItemGroup>
<Filter Include="Source Files">
<UniqueIdentifier>{4FC737F1-C7A5-4376-A066-2A32D752A2FF}</UniqueIdentifier>
<Extensions>cpp;c;cc;cxx;def;odl;idl;hpj;bat;asm;asmx</Extensions>
</Filter>
<Filter Include="Header Files">
<UniqueIdentifier>{93995380-89BD-4b04-88EB-625FBE52EBFB}</UniqueIdentifier>
<Extensions>h;hpp;hxx;hm;inl;inc;xsd</Extensions>
</Filter>
<Filter Include="Resource Files">
<UniqueIdentifier>{67DA6AB6-F800-4c08-8B7A-83BB121AAD01}</UniqueIdentifier>
<Extensions>rc;ico;cur;bmp;dlg;rc2;rct;bin;rgs;gif;jpg;jpeg;jpe;resx;tiff;tif;png;wav;mfcribbon-ms</Extensions>
</Filter>
</ItemGroup>
<ItemGroup>
<ClInclude Include="stdafx.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="targetver.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="zfs.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="NameValueList.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Pool.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="BlockReader.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Device.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="ZapObject.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Compress.h">
<Filter>Header Files</Filter>
</ClInclude>
<ClInclude Include="Hash.h">
<Filter>Header Files</Filter>
</ClInclude>
</ItemGroup>
<ItemGroup>
<ClCompile Include="stdafx.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="NameValueList.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Pool.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="BlockReader.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Device.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="main.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="ZapObject.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Compress.cpp">
<Filter>Source Files</Filter>
</ClCompile>
<ClCompile Include="Hash.cpp">
<Filter>Source Files</Filter>
</ClCompile>
</ItemGroup>
</Project>

1112
zfs-win/zfs.h Normal file

File diff suppressed because it is too large Load Diff