1
0
mirror of https://github.com/Zygo/bees.git synced 2025-05-17 13:25:45 +02:00
bees/include/crucible/extentwalker.h
Zygo Blaxell 6adaedeecd extentwalker: fix the binary search and add some debug infrastructure
Add some conditionally-compiled debug code, including an in-memory log
of what ExtentWalker does.  Dump that log on exceptions.

If we loop too many times in a debug build, kill the process so we can
stack trace.  In non-debug builds just throw a normal exception.

Grow the step size instead of shrinking it, to reduce the number of
binary search iterations.

Prevent a bug where the step size bottoms out before positioning the
target extent in the middle of the result vector.

Use the first extent for "first_extent", instead of the 3rd.

Get rid of some redundant checks.

Signed-off-by: Zygo Blaxell <bees@furryterror.org>
2021-06-11 20:56:54 -04:00

104 lines
2.3 KiB
C++

#ifndef CRUCIBLE_EXTENTWALKER_H
#define CRUCIBLE_EXTENTWALKER_H
#include "crucible/fd.h"
namespace crucible {
using namespace std;
// FIXME: ExtentCursor is probably a better name
struct Extent {
off_t m_begin = 0;
off_t m_end = 0;
uint64_t m_physical = 0;
uint64_t m_flags = 0;
// Btrfs extent reference details
off_t m_physical_len = 0;
off_t m_logical_len = 0;
off_t m_offset = 0;
// fiemap flags are uint32_t, so bits 32..63 are OK for us
// no extent here
static const uint64_t HOLE = (1ULL << 32);
// extent is physical space full of zeros
static const uint64_t PREALLOC = (1ULL << 33);
// extent's physical (RAM) size does not match logical (can we know this?)
static const uint64_t OBSCURED = (1ULL << 34);
operator bool() const;
off_t size() const;
off_t begin() const { return m_begin; }
off_t end() const { return m_end; }
uint64_t flags() const { return m_flags; }
uint64_t physical() const { return m_physical; }
off_t physical_len() const { return m_physical_len; }
off_t logical_len() const { return m_logical_len; }
off_t offset() const { return m_offset; }
bool compressed() const;
uint64_t bytenr() const;
bool operator==(const Extent &that) const;
bool operator!=(const Extent &that) const { return !(*this == that); }
Extent() = default;
Extent(const Extent &e) = default;
};
class ExtentWalker {
public:
using Vec = vector<Extent>;
using Itr = Vec::iterator;
protected:
Fd m_fd;
Stat m_stat;
virtual Vec get_extent_map(off_t pos);
private:
Vec m_extents;
Itr m_current;
Itr find_in_cache(off_t pos);
void run_fiemap(off_t pos);
#ifdef EXTENTWALKER_DEBUG
ostringstream m_log;
#endif
public:
ExtentWalker(Fd fd = Fd());
ExtentWalker(Fd fd, off_t initial_pos);
virtual ~ExtentWalker();
void reset();
Extent current();
bool next();
bool prev();
void seek(off_t new_pos);
friend ostream & operator<<(ostream &os, const ExtentWalker &ew);
};
class BtrfsExtentWalker : public ExtentWalker {
uint64_t m_tree_id;
Fd m_root_fd;
protected:
Vec get_extent_map(off_t pos) override;
public:
BtrfsExtentWalker(Fd fd);
BtrfsExtentWalker(Fd fd, off_t initial_pos);
BtrfsExtentWalker(Fd fd, off_t initial_pos, Fd root_fd);
void set_root_fd(Fd fd);
};
ostream &operator<<(ostream &os, const Extent &e);
};
#endif // CRUCIBLE_EXTENTWALKER_H