mirror of
https://github.com/versity/scoutfs.git
synced 2026-01-08 21:03:12 +00:00
Track the kernel changes to use the scoutfs_key struct as the btree key instead of a big-endian binary blob. Signed-off-by: Zach Brown <zab@versity.com>
145 lines
3.5 KiB
C
145 lines
3.5 KiB
C
#ifndef _SCOUTFS_KEY_H_
|
|
#define _SCOUTFS_KEY_H_
|
|
|
|
#include "sparse.h"
|
|
#include "util.h"
|
|
#include "format.h"
|
|
#include "cmp.h"
|
|
#include "endian_swap.h"
|
|
|
|
#define SK_FMT "%u.%llu.%u.%llu.%llu.%u"
|
|
/* This does not support null keys */
|
|
#define SK_ARG(key) (key)->sk_zone, le64_to_cpu((key)->_sk_first), \
|
|
(key)->sk_type, le64_to_cpu((key)->_sk_second), \
|
|
le64_to_cpu((key)->_sk_third), \
|
|
(key)->_sk_fourth
|
|
|
|
/*
|
|
* copy fields between keys with the same fields but different types.
|
|
* The destination type might have internal padding so we zero it.
|
|
*/
|
|
#define scoutfs_key_copy_types(a, b) \
|
|
do { \
|
|
__typeof__(a) _to = (a); \
|
|
__typeof__(b) _from = (b); \
|
|
\
|
|
memset(_to, 0, sizeof(*_to)); \
|
|
_to->sk_zone = _from->sk_zone; \
|
|
_to->_sk_first = _from->_sk_first; \
|
|
_to->sk_type = _from->sk_type; \
|
|
_to->_sk_second = _from->_sk_second; \
|
|
_to->_sk_third = _from->_sk_third; \
|
|
_to->_sk_fourth = _from->_sk_fourth; \
|
|
} while (0)
|
|
|
|
static inline void scoutfs_key_set_zeros(struct scoutfs_key *key)
|
|
{
|
|
key->sk_zone = 0;
|
|
key->_sk_first = 0;
|
|
key->sk_type = 0;
|
|
key->_sk_second = 0;
|
|
key->_sk_third = 0;
|
|
key->_sk_fourth = 0;
|
|
}
|
|
|
|
static inline void scoutfs_key_copy_or_zeros(struct scoutfs_key *dst,
|
|
struct scoutfs_key *src)
|
|
{
|
|
if (src)
|
|
*dst = *src;
|
|
else
|
|
scoutfs_key_set_zeros(dst);
|
|
}
|
|
|
|
static inline void scoutfs_key_set_ones(struct scoutfs_key *key)
|
|
{
|
|
key->sk_zone = U8_MAX;
|
|
key->_sk_first = cpu_to_le64(U64_MAX);
|
|
key->sk_type = U8_MAX;
|
|
key->_sk_second = cpu_to_le64(U64_MAX);
|
|
key->_sk_third = cpu_to_le64(U64_MAX);
|
|
key->_sk_fourth = U8_MAX;
|
|
}
|
|
|
|
/*
|
|
* Return a -1/0/1 comparison of keys.
|
|
*
|
|
* It turns out that these ternary chains are consistently cheaper than
|
|
* other alternatives across keys that first differ in any of the
|
|
* values. Say maybe 20% faster than memcmp.
|
|
*/
|
|
static inline int scoutfs_key_compare(struct scoutfs_key *a,
|
|
struct scoutfs_key *b)
|
|
{
|
|
return scoutfs_cmp(a->sk_zone, b->sk_zone) ?:
|
|
scoutfs_cmp(le64_to_cpu(a->_sk_first), le64_to_cpu(b->_sk_first)) ?:
|
|
scoutfs_cmp(a->sk_type, b->sk_type) ?:
|
|
scoutfs_cmp(le64_to_cpu(a->_sk_second), le64_to_cpu(b->_sk_second)) ?:
|
|
scoutfs_cmp(le64_to_cpu(a->_sk_third), le64_to_cpu(b->_sk_third)) ?:
|
|
scoutfs_cmp(a->_sk_fourth, b->_sk_fourth);
|
|
}
|
|
|
|
/*
|
|
* Compare ranges of keys where overlapping is equality. Returns:
|
|
* -1: a_end < b_start
|
|
* 1: a_start > b_end
|
|
* else 0: ranges overlap
|
|
*/
|
|
static inline int scoutfs_key_compare_ranges(struct scoutfs_key *a_start,
|
|
struct scoutfs_key *a_end,
|
|
struct scoutfs_key *b_start,
|
|
struct scoutfs_key *b_end)
|
|
{
|
|
return scoutfs_key_compare(a_end, b_start) < 0 ? -1 :
|
|
scoutfs_key_compare(a_start, b_end) > 0 ? 1 :
|
|
0;
|
|
}
|
|
|
|
static inline void scoutfs_key_inc(struct scoutfs_key *key)
|
|
{
|
|
if (++key->_sk_fourth != 0)
|
|
return;
|
|
|
|
le64_add_cpu(&key->_sk_third, 1);
|
|
if (key->_sk_third != 0)
|
|
return;
|
|
|
|
le64_add_cpu(&key->_sk_second, 1);
|
|
if (key->_sk_second != 0)
|
|
return;
|
|
|
|
if (++key->sk_type != 0)
|
|
return;
|
|
|
|
le64_add_cpu(&key->_sk_first, 1);
|
|
if (key->_sk_first != 0)
|
|
return;
|
|
|
|
key->sk_zone++;
|
|
}
|
|
|
|
static inline void scoutfs_key_dec(struct scoutfs_key *key)
|
|
{
|
|
if (--key->_sk_fourth != U8_MAX)
|
|
return;
|
|
|
|
le64_add_cpu(&key->_sk_third, -1);
|
|
if (key->_sk_third != cpu_to_le64(U64_MAX))
|
|
return;
|
|
|
|
le64_add_cpu(&key->_sk_second, -1);
|
|
if (key->_sk_second != cpu_to_le64(U64_MAX))
|
|
return;
|
|
|
|
if (--key->sk_type != U8_MAX)
|
|
return;
|
|
|
|
le64_add_cpu(&key->_sk_first, -1);
|
|
if (key->_sk_first != cpu_to_le64(U64_MAX))
|
|
return;
|
|
|
|
key->sk_zone--;
|
|
}
|
|
|
|
#endif
|