mirror of
https://github.com/dominicusin/zfs-win
synced 2025-08-22 01:58:20 +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:
commit
1150b29fbe
25
common.props
Normal file
25
common.props
Normal 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
16
debug.props
Normal 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
26
release.props
Normal 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
20
zfs-win.sln
Normal 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
164
zfs-win/BlockReader.cpp
Normal 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
47
zfs-win/BlockReader.h
Normal 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
155
zfs-win/Compress.cpp
Normal 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
31
zfs-win/Compress.h
Normal 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
351
zfs-win/Device.cpp
Normal 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
91
zfs-win/Device.h
Normal 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
247
zfs-win/Hash.cpp
Normal 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
138
zfs-win/Hash.h
Normal 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
249
zfs-win/NameValueList.cpp
Normal 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
98
zfs-win/NameValueList.h
Normal 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
132
zfs-win/Pool.cpp
Normal 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
46
zfs-win/Pool.h
Normal 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
182
zfs-win/ZapObject.cpp
Normal 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
41
zfs-win/ZapObject.h
Normal 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
210
zfs-win/main.cpp
Normal 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
29
zfs-win/stdafx.cpp
Normal 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
55
zfs-win/stdafx.h
Normal 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
29
zfs-win/targetver.h
Normal 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
93
zfs-win/zfs-win.vcxproj
Normal 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>
|
78
zfs-win/zfs-win.vcxproj.filters
Normal file
78
zfs-win/zfs-win.vcxproj.filters
Normal 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
1112
zfs-win/zfs.h
Normal file
File diff suppressed because it is too large
Load Diff
Loading…
x
Reference in New Issue
Block a user