__le32 tv_nsec;
} __attribute__ ((packed));
+
+/*
+ * frag encoding:
+ * 8 upper bits = "bits"
+ * 24 lower bits = "value"
+ * (We could go to 5+27 bits, but who cares.)
+ *
+ * We use the _most_ significant bits of the 24 bit value. This makes
+ * values logically sort.
+ *
+ * Unfortunately, because the bits are still in the high bits, we
+ * can't sort encoded frags numerically. However, it does allow you
+ * to feed encoded frags as values into frag_contains_value.
+ */
+static inline __u32 frag_make(__u32 b, __u32 v) {
+ return (b << 24) |
+ (v & (0xffffffu << (24-b)) & 0xffffffu);
+}
+static inline __u32 frag_bits(__u32 f) { return f >> 24; }
+static inline __u32 frag_value(__u32 f) { return f & 0xffffffu; }
+static inline __u32 frag_mask(__u32 f) {
+ return (0xffffffu << (24-frag_bits(f))) & 0xffffffu;
+}
+static inline __u32 frag_mask_shift(__u32 f) {
+ return 24 - frag_bits(f);
+}
+
+static inline bool frag_contains_value(__u32 f, __u32 v) {
+ return (v & frag_mask(f)) == frag_value(f);
+}
+static inline bool frag_contains_frag(__u32 f, __u32 sub) {
+ /* as specific as us, and contained by us */
+ return frag_bits(sub) >= frag_bits(f) &&
+ (frag_value(sub) & frag_mask(f)) == frag_value(f);
+}
+
+static inline __u32 frag_parent(__u32 f) {
+ return frag_make(frag_bits(f) - 1,
+ frag_value(f) & (frag_mask(f) << 1));
+}
+static inline bool frag_is_left_child(__u32 f) {
+ return frag_bits(f) > 0 &&
+ (frag_value(f) & (0x1000000 >> frag_bits(f)) == 0);
+}
+static inline bool frag_is_right_child(__u32 f) {
+ return frag_bits(f) > 0 &&
+ (frag_value(f) & (0x1000000 >> frag_bits(f)) == 1);
+}
+static inline __u32 frag_sibling(__u32 f) {
+ return frag_make(frag_bits(f),
+ frag_value(f) ^ (0x1000000 >> frag_bits(f)));
+}
+static inline __u32 frag_left_child(__u32 f) {
+ return frag_make(frag_bits(f)+1, frag_value(f));
+}
+static inline __u32 frag_right_child(__u32 f) {
+ return frag_make(frag_bits(f)+1,
+ frag_value(f) | (0x1000000 >> (1+frag_bits(f))));
+}
+static inline __u32 frag_make_child(__u32 f, int by, int i) {
+ int newbits = frag_bits(f) + by;
+ return frag_make(newbits,
+ frag_value(f) | (i << (24 - newbits)));
+}
+static inline bool frag_is_leftmost(__u32 f) {
+ return frag_value(f) == 0;
+}
+static inline bool frag_is_rightmost(__u32 f) {
+ return frag_value(f) == frag_mask(f);
+}
+static inline __u32 frag_next(__u32 f) {
+ return frag_make(frag_bits(f),
+ frag_value(f) + (0x1000000 >> frag_bits(f)));
+}
+
+
+#if 0
/*
* dir fragments
* 8 upper bits = "bits"
- * 23 lower bits = "value"
+ * 24 lower bits = "value"
+ *
+ * We use the _least_ significant bits.
*
* This isn't quite ideal in that it doesn't sort well, and because we
* are masking out the least significant bits instead of hte most
}
return frag_make(0, 0); /* rightmost */
}
+#endif
-/*
- * note: this is not in a "nice" sorted order, by any means.
- */
static inline int frag_compare(__u32 a, __u32 b) {
unsigned va = frag_value(a);
unsigned vb = frag_value(b);
return 0;
}
-
/*
* object layout - how objects are mapped into PGs
*/
typedef uint32_t _frag_t;
class frag_t {
- /* encoded value.
- * 8 upper bits = "bits"
- * 24 lower bits = "value"
+ /*
+ * encoding is dictated by frag_* functions in ceph_fs.h. use those
+ * helpers _exclusively_.
*/
public:
_frag_t _enc;
unsigned value() const { return frag_value(_enc); }
unsigned bits() const { return frag_bits(_enc); }
unsigned mask() const { return frag_mask(_enc); }
+ unsigned mask_shift() const { return frag_mask_shift(_enc); }
operator _frag_t() const { return _enc; }
}
// splitting
+ frag_t make_child(int i, int nb) const {
+ assert(i < (1<<nb));
+ return frag_t(frag_make_child(_enc, nb, i));
+ }
void split(int nb, std::list<frag_t>& fragments) const {
assert(nb > 0);
unsigned nway = 1 << nb;
for (unsigned i=0; i<nway; i++)
- fragments.push_back( frag_t(value() | (i << bits()),
- bits()+nb) );
+ fragments.push_back(make_child(i, nb));
}
// binary splitting
+ frag_t left_child() const { return frag_t(frag_left_child(_enc)); }
+ frag_t right_child() const { return frag_t(frag_right_child(_enc)); }
+
+ bool is_left() const { return frag_is_left_child(_enc); }
+ bool is_right() const { return frag_is_right_child(_enc); }
frag_t get_sibling() const {
assert(!is_root());
return frag_t(frag_sibling(_enc));
}
- bool is_left() const { return frag_is_left_child(_enc); }
- bool is_right() const { return frag_is_right_child(_enc); }
- frag_t left_child() const { return frag_t(frag_left_child(_enc)); }
- frag_t right_child() const { return frag_t(frag_right_child(_enc)); }
// sequencing
bool is_leftmost() const { return frag_is_leftmost(_enc); }
unsigned nway = 1 << nb;
unsigned i;
for (i=0; i<nway; i++) {
- frag_t n(t.value() | (i << t.bits()),
- t.bits()+nb);
+ frag_t n = t.make_child(i, nb);
if (n.contains(v)) {
t = n;
break;