mirror of
https://github.com/Zygo/bees.git
synced 2025-05-17 21:35:45 +02:00
This complements the already existing support for reading the fields of a root backref. Signed-off-by: Zygo Blaxell <bees@furryterror.org>
217 lines
6.6 KiB
C++
217 lines
6.6 KiB
C++
#ifndef CRUCIBLE_BTRFS_TREE_H
|
|
#define CRUCIBLE_BTRFS_TREE_H
|
|
|
|
#include "crucible/fd.h"
|
|
#include "crucible/fs.h"
|
|
#include "crucible/bytevector.h"
|
|
|
|
namespace crucible {
|
|
using namespace std;
|
|
|
|
class BtrfsTreeItem {
|
|
uint64_t m_objectid = 0;
|
|
uint64_t m_offset = 0;
|
|
uint64_t m_transid = 0;
|
|
ByteVector m_data;
|
|
uint8_t m_type = 0;
|
|
public:
|
|
uint64_t objectid() const { return m_objectid; }
|
|
uint64_t offset() const { return m_offset; }
|
|
uint64_t transid() const { return m_transid; }
|
|
uint8_t type() const { return m_type; }
|
|
const ByteVector data() const { return m_data; }
|
|
BtrfsTreeItem() = default;
|
|
BtrfsTreeItem(const BtrfsIoctlSearchHeader &bish);
|
|
BtrfsTreeItem& operator=(const BtrfsIoctlSearchHeader &bish);
|
|
bool operator!() const;
|
|
|
|
/// Member access methods. Invoking a method on the
|
|
/// wrong type of item will throw an exception.
|
|
|
|
/// @{ Block group items
|
|
uint64_t block_group_flags() const;
|
|
uint64_t block_group_used() const;
|
|
/// @}
|
|
|
|
/// @{ Chunk items
|
|
uint64_t chunk_length() const;
|
|
uint64_t chunk_type() const;
|
|
/// @}
|
|
|
|
/// @{ Dev extent items (physical byte ranges)
|
|
uint64_t dev_extent_chunk_offset() const;
|
|
uint64_t dev_extent_length() const;
|
|
/// @}
|
|
|
|
/// @{ Dev items (devices)
|
|
uint64_t dev_item_total_bytes() const;
|
|
uint64_t dev_item_bytes_used() const;
|
|
/// @}
|
|
|
|
/// @{ Inode items
|
|
uint64_t inode_size() const;
|
|
/// @}
|
|
|
|
/// @{ Extent refs (EXTENT_DATA)
|
|
uint64_t file_extent_logical_bytes() const;
|
|
uint64_t file_extent_generation() const;
|
|
uint64_t file_extent_offset() const;
|
|
uint64_t file_extent_bytenr() const;
|
|
uint8_t file_extent_type() const;
|
|
btrfs_compression_type file_extent_compression() const;
|
|
/// @}
|
|
|
|
/// @{ Extent items (EXTENT_ITEM)
|
|
uint64_t extent_begin() const;
|
|
uint64_t extent_end() const;
|
|
uint64_t extent_flags() const;
|
|
uint64_t extent_generation() const;
|
|
/// @}
|
|
|
|
/// @{ Root items
|
|
uint64_t root_flags() const;
|
|
uint64_t root_refs() const;
|
|
/// @}
|
|
|
|
/// @{ Root backref items.
|
|
uint64_t root_ref_dirid() const;
|
|
string root_ref_name() const;
|
|
uint64_t root_ref_parent_rootid() const;
|
|
/// @}
|
|
};
|
|
|
|
ostream &operator<<(ostream &os, const BtrfsTreeItem &bti);
|
|
|
|
class BtrfsTreeFetcher {
|
|
protected:
|
|
Fd m_fd;
|
|
BtrfsIoctlSearchKey m_sk;
|
|
uint64_t m_tree = 0;
|
|
uint64_t m_min_transid = 0;
|
|
uint64_t m_max_transid = numeric_limits<uint64_t>::max();
|
|
uint64_t m_block_size = 0;
|
|
uint64_t m_lookbehind_size = 0;
|
|
uint64_t m_scale_size = 0;
|
|
uint8_t m_type = 0;
|
|
|
|
uint64_t scale_logical(uint64_t logical) const;
|
|
uint64_t unscale_logical(uint64_t logical) const;
|
|
const static uint64_t s_max_logical = numeric_limits<uint64_t>::max();
|
|
uint64_t scaled_max_logical() const;
|
|
|
|
virtual void fill_sk(BtrfsIoctlSearchKey &key, uint64_t object);
|
|
virtual void next_sk(BtrfsIoctlSearchKey &key, const BtrfsIoctlSearchHeader &hdr);
|
|
virtual uint64_t hdr_logical(const BtrfsIoctlSearchHeader &hdr) = 0;
|
|
virtual bool hdr_match(const BtrfsIoctlSearchHeader &hdr) = 0;
|
|
virtual bool hdr_stop(const BtrfsIoctlSearchHeader &hdr) = 0;
|
|
Fd fd() const;
|
|
void fd(Fd fd);
|
|
public:
|
|
virtual ~BtrfsTreeFetcher() = default;
|
|
BtrfsTreeFetcher(Fd new_fd);
|
|
void type(uint8_t type);
|
|
uint8_t type();
|
|
void tree(uint64_t tree);
|
|
uint64_t tree();
|
|
void transid(uint64_t min_transid, uint64_t max_transid = numeric_limits<uint64_t>::max());
|
|
/// Block size (sectorsize) of filesystem
|
|
uint64_t block_size() const;
|
|
/// Fetch last object < logical, null if not found
|
|
BtrfsTreeItem prev(uint64_t logical);
|
|
/// Fetch first object > logical, null if not found
|
|
BtrfsTreeItem next(uint64_t logical);
|
|
/// Fetch object at exactly logical, null if not found
|
|
BtrfsTreeItem at(uint64_t);
|
|
/// Fetch first object >= logical
|
|
BtrfsTreeItem lower_bound(uint64_t logical);
|
|
/// Fetch last object <= logical
|
|
BtrfsTreeItem rlower_bound(uint64_t logical);
|
|
|
|
/// Estimated distance between objects
|
|
virtual uint64_t lookbehind_size() const;
|
|
virtual void lookbehind_size(uint64_t);
|
|
|
|
/// Scale size (normally block size but must be set to 1 for fs trees)
|
|
uint64_t scale_size() const;
|
|
void scale_size(uint64_t);
|
|
};
|
|
|
|
class BtrfsTreeObjectFetcher : public BtrfsTreeFetcher {
|
|
protected:
|
|
virtual void fill_sk(BtrfsIoctlSearchKey &key, uint64_t logical) override;
|
|
virtual uint64_t hdr_logical(const BtrfsIoctlSearchHeader &hdr) override;
|
|
virtual bool hdr_match(const BtrfsIoctlSearchHeader &hdr) override;
|
|
virtual bool hdr_stop(const BtrfsIoctlSearchHeader &hdr) override;
|
|
public:
|
|
using BtrfsTreeFetcher::BtrfsTreeFetcher;
|
|
};
|
|
|
|
class BtrfsTreeOffsetFetcher : public BtrfsTreeFetcher {
|
|
protected:
|
|
uint64_t m_objectid = 0;
|
|
virtual void fill_sk(BtrfsIoctlSearchKey &key, uint64_t offset) override;
|
|
virtual uint64_t hdr_logical(const BtrfsIoctlSearchHeader &hdr) override;
|
|
virtual bool hdr_match(const BtrfsIoctlSearchHeader &hdr) override;
|
|
virtual bool hdr_stop(const BtrfsIoctlSearchHeader &hdr) override;
|
|
public:
|
|
using BtrfsTreeFetcher::BtrfsTreeFetcher;
|
|
void objectid(uint64_t objectid);
|
|
uint64_t objectid() const;
|
|
};
|
|
|
|
class BtrfsCsumTreeFetcher : public BtrfsTreeOffsetFetcher {
|
|
public:
|
|
const uint32_t BTRFS_CSUM_TYPE_UNKNOWN = uint32_t(1) << 16;
|
|
private:
|
|
size_t m_sum_size = 0;
|
|
uint32_t m_sum_type = BTRFS_CSUM_TYPE_UNKNOWN;
|
|
public:
|
|
BtrfsCsumTreeFetcher(const Fd &fd);
|
|
|
|
uint32_t sum_type() const;
|
|
size_t sum_size() const;
|
|
void get_sums(uint64_t logical, size_t count, function<void(uint64_t logical, const uint8_t *buf, size_t count)> output);
|
|
};
|
|
|
|
/// Fetch extent items from extent tree.
|
|
/// Does not filter out metadata! See BtrfsDataExtentTreeFetcher for that.
|
|
class BtrfsExtentItemFetcher : public BtrfsTreeObjectFetcher {
|
|
public:
|
|
BtrfsExtentItemFetcher(const Fd &fd);
|
|
};
|
|
|
|
/// Fetch extent refs from an inode. Caller must set the tree and objectid.
|
|
class BtrfsExtentDataFetcher : public BtrfsTreeOffsetFetcher {
|
|
public:
|
|
BtrfsExtentDataFetcher(const Fd &fd);
|
|
};
|
|
|
|
/// Fetch raw inode items
|
|
class BtrfsInodeFetcher : public BtrfsTreeObjectFetcher {
|
|
public:
|
|
BtrfsInodeFetcher(const Fd &fd);
|
|
BtrfsTreeItem stat(uint64_t subvol, uint64_t inode);
|
|
};
|
|
|
|
/// Fetch a root (subvol) item
|
|
class BtrfsRootFetcher : public BtrfsTreeObjectFetcher {
|
|
public:
|
|
BtrfsRootFetcher(const Fd &fd);
|
|
BtrfsTreeItem root(uint64_t subvol);
|
|
BtrfsTreeItem root_backref(uint64_t subvol);
|
|
};
|
|
|
|
/// Fetch data extent items from extent tree, skipping metadata-only block groups
|
|
class BtrfsDataExtentTreeFetcher : public BtrfsExtentItemFetcher {
|
|
BtrfsTreeItem m_current_bg;
|
|
BtrfsTreeOffsetFetcher m_chunk_tree;
|
|
protected:
|
|
virtual void next_sk(BtrfsIoctlSearchKey &key, const BtrfsIoctlSearchHeader &hdr) override;
|
|
public:
|
|
BtrfsDataExtentTreeFetcher(const Fd &fd);
|
|
};
|
|
|
|
}
|
|
|
|
#endif
|