mirror of
https://github.com/dominicusin/zfs-win
synced 2025-08-30 13:57:58 +00:00
More work on the ObjectSet class.
This commit is contained in:
@@ -12,12 +12,90 @@ namespace ZFS
|
||||
{
|
||||
}
|
||||
|
||||
bool ObjectSet::Init(std::vector<uint8_t>& objset, std::vector<uint8_t>& dnode)
|
||||
bool ObjectSet::Read(Pool& pool, blkptr_t* bp, size_t count)
|
||||
{
|
||||
m_objset.swap(objset);
|
||||
m_dnode.swap(dnode);
|
||||
ASSERT(bp->type == DMU_OT_OBJSET);
|
||||
|
||||
m_objset.clear();
|
||||
m_dnode.clear();
|
||||
m_dnode_count = 0;
|
||||
|
||||
if(!pool.Read(m_objset, bp, count))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
objset_phys_t* os = (objset_phys_t*)m_objset.data();
|
||||
|
||||
if(os->meta_dnode.type != DMU_OT_DNODE)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if(!pool.Read(m_dnode, os->meta_dnode.blkptr, os->meta_dnode.nblkptr))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
m_dnode_count = m_dnode.size() / sizeof(dnode_phys_t);
|
||||
|
||||
if(os->type == DMU_OST_META || os->type == DMU_OST_ZFS)
|
||||
{
|
||||
if(m_dnode_count < 2)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
dnode_phys_t* dn = (*this)[1];
|
||||
|
||||
if(os->type == DMU_OST_META && dn->type != DMU_OT_OBJECT_DIRECTORY
|
||||
|| os->type == DMU_OST_ZFS && dn->type != DMU_OT_MASTER_NODE)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
if(!m_objdir.Read(pool, dn->blkptr, dn->nblkptr))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
objset_phys_t* ObjectSet::operator -> ()
|
||||
{
|
||||
ASSERT(m_objset.size() >= sizeof(objset_phys_t));
|
||||
|
||||
return (objset_phys_t*)m_objset.data();
|
||||
}
|
||||
|
||||
dnode_phys_t* ObjectSet::operator [] (size_t index)
|
||||
{
|
||||
ASSERT(index < m_dnode_count);
|
||||
|
||||
return (dnode_phys_t*)m_dnode.data() + index;
|
||||
}
|
||||
|
||||
dnode_phys_t* ObjectSet::operator [] (const char* s)
|
||||
{
|
||||
uint64_t index;
|
||||
|
||||
if(m_objdir.Lookup(s, index))
|
||||
{
|
||||
size_t i = (size_t)index;
|
||||
|
||||
if(i < m_dnode_count)
|
||||
{
|
||||
return (*this)[i];
|
||||
}
|
||||
}
|
||||
|
||||
return NULL;
|
||||
}
|
||||
|
||||
size_t ObjectSet::count()
|
||||
{
|
||||
return m_dnode_count;
|
||||
}
|
||||
}
|
@@ -1,6 +1,7 @@
|
||||
#pragma once
|
||||
|
||||
#include "zfs.h"
|
||||
#include "Pool.h"
|
||||
#include "ZapObject.h"
|
||||
|
||||
namespace ZFS
|
||||
{
|
||||
@@ -9,15 +10,17 @@ namespace ZFS
|
||||
std::vector<uint8_t> m_objset;
|
||||
std::vector<uint8_t> m_dnode;
|
||||
size_t m_dnode_count;
|
||||
ZapObject m_objdir;
|
||||
|
||||
public:
|
||||
ObjectSet();
|
||||
virtual ~ObjectSet();
|
||||
|
||||
bool Init(std::vector<uint8_t>& objset, std::vector<uint8_t>& dnode);
|
||||
bool Read(Pool& pool, blkptr_t* bp, size_t count);
|
||||
|
||||
objset_phys_t* operator -> () {ASSERT(m_objset.size() >= sizeof(objset_phys_t)); return (objset_phys_t*)m_objset.data();}
|
||||
dnode_phys_t* operator [] (size_t index) {ASSERT(index < m_dnode_count); return (dnode_phys_t*)m_dnode.data() + index;}
|
||||
size_t count() {return m_dnode_count;}
|
||||
objset_phys_t* operator -> ();
|
||||
dnode_phys_t* operator [] (size_t index);
|
||||
dnode_phys_t* operator [] (const char* s);
|
||||
size_t count();
|
||||
};
|
||||
}
|
||||
|
@@ -129,40 +129,4 @@ namespace ZFS
|
||||
|
||||
return r.ReadToEnd(buff);
|
||||
}
|
||||
|
||||
bool Pool::Read(ObjectSet& objset, blkptr_t* bp, size_t count)
|
||||
{
|
||||
ASSERT(bp->type == DMU_OT_OBJSET);
|
||||
|
||||
std::vector<uint8_t> buff[2];
|
||||
|
||||
if(Read(buff[0], bp, count))
|
||||
{
|
||||
objset_phys_t* os = (objset_phys_t*)buff[0].data();
|
||||
|
||||
if(os->meta_dnode.type == DMU_OT_DNODE)
|
||||
{
|
||||
if(Read(buff[1], os->meta_dnode.blkptr, os->meta_dnode.nblkptr))
|
||||
{
|
||||
return objset.Init(buff[0], buff[1]);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
||||
bool Pool::Read(ZapObject& zap, blkptr_t* bp, size_t count)
|
||||
{
|
||||
std::vector<uint8_t> buff;
|
||||
|
||||
if(Read(buff, bp, count))
|
||||
{
|
||||
zap.Parse(buff);
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
@@ -23,8 +23,6 @@
|
||||
|
||||
#include "zfs.h"
|
||||
#include "Device.h"
|
||||
#include "ZapObject.h"
|
||||
#include "ObjectSet.h"
|
||||
|
||||
namespace ZFS
|
||||
{
|
||||
@@ -44,7 +42,5 @@ namespace ZFS
|
||||
void Close();
|
||||
|
||||
bool Read(std::vector<uint8_t>& buff, blkptr_t* bp, size_t count);
|
||||
bool Read(ObjectSet& objset, blkptr_t* bp, size_t count);
|
||||
bool Read(ZapObject& zap, blkptr_t* bp, size_t count);
|
||||
};
|
||||
}
|
@@ -30,30 +30,32 @@ namespace ZFS
|
||||
|
||||
ZapObject::~ZapObject()
|
||||
{
|
||||
Clear();
|
||||
RemoveAll();
|
||||
}
|
||||
|
||||
void ZapObject::Parse(std::vector<uint8_t>& buff)
|
||||
bool ZapObject::Read(Pool& pool, blkptr_t* bp, size_t count)
|
||||
{
|
||||
Clear();
|
||||
RemoveAll();
|
||||
|
||||
if(buff.size() >= sizeof(uint64_t))
|
||||
std::vector<uint8_t> buff;
|
||||
|
||||
if(pool.Read(buff, bp, count))
|
||||
{
|
||||
uint64_t* ptr = (uint64_t*)buff.data();
|
||||
|
||||
if(*ptr == ZBT_MICRO) ParseMicro(buff);
|
||||
else if(*ptr == ZBT_HEADER) ParseFat(buff);
|
||||
}
|
||||
}
|
||||
|
||||
void ZapObject::Clear()
|
||||
{
|
||||
for(auto i = begin(); i != end(); i++)
|
||||
{
|
||||
delete i->second;
|
||||
if(buff.size() >= sizeof(uint64_t))
|
||||
{
|
||||
switch(*(uint64_t*)buff.data())
|
||||
{
|
||||
case ZBT_MICRO:
|
||||
ParseMicro(buff);
|
||||
return true;
|
||||
case ZBT_HEADER:
|
||||
ParseFat(buff);
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
clear();
|
||||
return false;
|
||||
}
|
||||
|
||||
bool ZapObject::Lookup(const char* name, uint64_t& value)
|
||||
@@ -87,6 +89,16 @@ namespace ZFS
|
||||
return false;
|
||||
}
|
||||
|
||||
void ZapObject::RemoveAll()
|
||||
{
|
||||
for(auto i = begin(); i != end(); i++)
|
||||
{
|
||||
delete i->second;
|
||||
}
|
||||
|
||||
clear();
|
||||
}
|
||||
|
||||
void ZapObject::ParseMicro(std::vector<uint8_t>& buff)
|
||||
{
|
||||
mzap_phys_t* mzap = (mzap_phys_t*)buff.data();
|
||||
|
@@ -21,12 +21,13 @@
|
||||
|
||||
#pragma once
|
||||
|
||||
#include "zfs.h"
|
||||
#include "Pool.h"
|
||||
|
||||
namespace ZFS
|
||||
{
|
||||
class ZapObject : protected std::map<std::string, std::vector<uint8_t>*>
|
||||
{
|
||||
void RemoveAll();
|
||||
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);
|
||||
@@ -35,8 +36,7 @@ namespace ZFS
|
||||
ZapObject();
|
||||
virtual ~ZapObject();
|
||||
|
||||
void Parse(std::vector<uint8_t>& buff);
|
||||
void Clear();
|
||||
bool Read(Pool& pool, blkptr_t* bp, size_t count);
|
||||
|
||||
bool Lookup(const char* name, uint64_t& value);
|
||||
bool Lookup(const char* name, std::string& value);
|
||||
|
@@ -22,6 +22,7 @@
|
||||
#include "stdafx.h"
|
||||
#include "Pool.h"
|
||||
#include "Device.h"
|
||||
#include "ObjectSet.h"
|
||||
#include "ZapObject.h"
|
||||
|
||||
int _tmain(int argc, _TCHAR* argv[])
|
||||
@@ -72,47 +73,27 @@ int _tmain(int argc, _TCHAR* argv[])
|
||||
|
||||
ZFS::ObjectSet os;
|
||||
|
||||
if(p.Read(os, &dev->m_active->rootbp, 1))
|
||||
if(os.Read(p, &dev->m_active->rootbp, 1))
|
||||
{
|
||||
ASSERT(os.count() > 2);
|
||||
|
||||
dnode_phys_t* root_dataset = NULL;
|
||||
|
||||
ASSERT(os[1]->type == DMU_OT_OBJECT_DIRECTORY);
|
||||
|
||||
if(os[1]->type == DMU_OT_OBJECT_DIRECTORY)
|
||||
{
|
||||
ZFS::ZapObject zap;
|
||||
|
||||
if(p.Read(zap, os[1]->blkptr, os[1]->nblkptr))
|
||||
{
|
||||
uint64_t index;
|
||||
|
||||
if(zap.Lookup("root_dataset", index))
|
||||
{
|
||||
if(index < os.count() && os[index]->type == DMU_OT_DSL_DIR)
|
||||
{
|
||||
root_dataset = os[index];
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
dnode_phys_t* root_dataset = os["root_dataset"];
|
||||
|
||||
dnode_phys_t* head_dataset = NULL;
|
||||
|
||||
if(root_dataset != NULL)
|
||||
if(root_dataset != NULL && root_dataset->type == DMU_OT_DSL_DIR)
|
||||
{
|
||||
dsl_dir_phys_t* dir = (dsl_dir_phys_t*)root_dataset->bonus;
|
||||
|
||||
size_t index = (size_t)dir->head_dataset_obj;
|
||||
|
||||
if(index < os.count() && os[index]->type == DMU_OT_DSL_DATASET)
|
||||
if(index < os.count())
|
||||
{
|
||||
head_dataset = os[index];
|
||||
}
|
||||
}
|
||||
|
||||
if(head_dataset != NULL)
|
||||
if(head_dataset != NULL && head_dataset->type == DMU_OT_DSL_DATASET)
|
||||
{
|
||||
dsl_dataset_phys_t* ds = (dsl_dataset_phys_t*)head_dataset->bonus;
|
||||
|
||||
@@ -120,35 +101,11 @@ int _tmain(int argc, _TCHAR* argv[])
|
||||
{
|
||||
ZFS::ObjectSet os;
|
||||
|
||||
if(p.Read(os, &ds->bp, 1))
|
||||
if(os.Read(p, &ds->bp, 1))
|
||||
{
|
||||
dnode_phys_t* root = NULL;
|
||||
dnode_phys_t* root = os["ROOT"];
|
||||
|
||||
ASSERT(os[1]->type == DMU_OT_MASTER_NODE);
|
||||
|
||||
if(os[1]->type == DMU_OT_MASTER_NODE)
|
||||
{
|
||||
ZFS::ZapObject zap;
|
||||
|
||||
if(p.Read(zap, os[1]->blkptr, os[1]->nblkptr))
|
||||
{
|
||||
uint64_t index;
|
||||
|
||||
if(zap.Lookup("ROOT", index)) // NOTE: the ROOT dataset may not contain too many files, don't be surprised
|
||||
{
|
||||
if(index < os.count() && os[index]->type == DMU_OT_DIRECTORY_CONTENTS)
|
||||
{
|
||||
root = os[index];
|
||||
}
|
||||
else
|
||||
{
|
||||
ASSERT(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
if(root != NULL)
|
||||
if(root != NULL && root->type == DMU_OT_DIRECTORY_CONTENTS)
|
||||
{
|
||||
znode_phys_t* node = (znode_phys_t*)root->bonus;
|
||||
|
||||
|
Reference in New Issue
Block a user