scoutfs: remove dead block mapping code

Remove all the code for tracking block mapping items and storing free
blocks in bitmaps.

Signed-off-by: Zach Brown <zab@versity.com>
This commit is contained in:
Zach Brown
2018-04-06 14:55:59 -07:00
committed by Zach Brown
parent 70b2a50c9a
commit 5eddd10eb7
5 changed files with 3 additions and 842 deletions

View File

@@ -224,23 +224,6 @@ static inline const struct scoutfs_item_count SIC_WRITE_BEGIN(void)
return cnt;
}
/*
* Truncating a block mapping item's worth of blocks can modify both
* free blkno and free segno items per block. Then the largest possible
* mapping item.
*/
static inline const struct scoutfs_item_count SIC_TRUNC_BLOCK(void)
{
struct scoutfs_item_count cnt = {0,};
unsigned nr_free = (2 * SCOUTFS_BLOCK_MAPPING_BLOCKS);
cnt.items += 1 + nr_free;
cnt.vals += SCOUTFS_BLOCK_MAPPING_MAX_BYTES +
(nr_free * sizeof(struct scoutfs_free_bits));
return cnt;
}
/*
* Truncating an extent can:
* - delete existing file extent,

View File

@@ -18,7 +18,6 @@
#include <linux/sched.h>
#include <linux/buffer_head.h>
#include <linux/hash.h>
#include <linux/random.h>
#include <linux/log2.h>
#include "format.h"
@@ -84,488 +83,6 @@ struct task_cursor {
pid_t pid;
};
#if 0
/*
* Block mapping items and their native decoded form can be pretty big.
* Let's allocate them to avoid blowing the stack.
*/
struct block_mapping {
/* native representation */
unsigned long offline[DIV_ROUND_UP(SCOUTFS_BLOCK_MAPPING_BLOCKS,
BITS_PER_LONG)];
u64 blknos[SCOUTFS_BLOCK_MAPPING_BLOCKS];
/* encoded persistent item */
u8 encoded[SCOUTFS_BLOCK_MAPPING_MAX_BYTES];
} __packed;
/*
* We encode u64 blknos as a vlq zigzag encoded delta from the previous
* blkno. zigzag moves the sign bit down into the lsb so that small
* negative values have very few bits set. Then vlq outputs the least
* significant set bits into bytes in groups of 7.
*
* https://en.wikipedia.org/wiki/Variable-length_quantity
*
* The end result is that a series of blknos, which are limited by
* device size and often allocated near each other, are encoded with a
* handful of bytes.
*/
static unsigned zigzag_encode(u8 *bytes, u64 prev, u64 x)
{
unsigned pos = 0;
x -= prev;
/* careful, relying on shifting extending the sign bit */
x = (x << 1) ^ ((s64)x >> 63);
do {
bytes[pos++] = x & 127;
x >>= 7;
} while (x);
bytes[pos - 1] |= 128;
return pos;
}
static int zigzag_decode(u64 *res, u64 prev, u8 *bytes, unsigned len)
{
unsigned shift = 0;
int ret = -EIO;
u64 x = 0;
int i;
u8 b;
for (i = 0; i < len; i++) {
b = bytes[i];
x |= (u64)(b & 127) << shift;
if (b & 128) {
ret = i + 1;
break;
}
shift += 7;
/* falls through to return -EIO if we run out of bytes */
}
x = (x >> 1) ^ (-(x & 1));
*res = prev + x;
return ret;
}
/*
* Block mappings are encoded into a byte stream.
*
* The first byte's low bits contains the last mapping index that will
* be decoded.
*
* As we walk through the encoded blocks we add control bits to the
* current control byte for the encoding of the block: zero, offline,
* increment from prev, or zigzag encoding.
*
* When the control byte is full we start filling the next byte in the
* output as the control byte for the coming blocks. When we zigzag
* encode blocks we add them to the output stream. The result is an
* interleaving of control bytes and zigzag blocks, when they're needed.
*
* In practice the typical mapping will have a zigzag for the first
* block and then the rest will be described by the control bits.
* Regions of sparse, advancing allocations, and offline are all
* described only by control bits, getting us down to 2 bits per block.
*/
static unsigned encode_mapping(struct block_mapping *map)
{
unsigned shift;
unsigned len;
u64 blkno;
u64 prev;
u8 *enc;
u8 *ctl;
u8 last;
int ret;
int i;
enc = map->encoded;
ctl = enc++;
len = 1;
/* find the last set block in the mapping */
last = SCOUTFS_BLOCK_MAPPING_BLOCKS;
for (i = 0; i < SCOUTFS_BLOCK_MAPPING_BLOCKS; i++) {
if (map->blknos[i] || test_bit(i, map->offline))
last = i;
}
if (last == SCOUTFS_BLOCK_MAPPING_BLOCKS)
return 0;
/* start with 6 bits of last */
*ctl = last;
shift = 6;
prev = 0;
for (i = 0; i <= last; i++) {
blkno = map->blknos[i];
if (shift == 8) {
ctl = enc++;
len++;
*ctl = 0;
shift = 0;
}
if (blkno == prev + 1)
*ctl |= (SCOUTFS_BLOCK_ENC_INC << shift);
else if (test_bit(i, map->offline))
*ctl |= (SCOUTFS_BLOCK_ENC_OFFLINE << shift);
else if (!blkno)
*ctl |= (SCOUTFS_BLOCK_ENC_ZERO << shift);
else {
*ctl |= (SCOUTFS_BLOCK_ENC_DELTA << shift);
ret = zigzag_encode(enc, prev, blkno);
enc += ret;
len += ret;
}
shift += 2;
if (blkno)
prev = blkno;
}
return len;
}
static int decode_mapping(struct block_mapping *map, int size)
{
unsigned ctl_bits;
u64 blkno;
u64 prev;
u8 *enc;
u8 ctl;
u8 last;
int ret;
int i;
if (size < 1 || size > SCOUTFS_BLOCK_MAPPING_MAX_BYTES)
return -EIO;
memset(map->blknos, 0, sizeof(map->blknos));
memset(map->offline, 0, sizeof(map->offline));
enc = map->encoded;
ctl = *(enc++);
size--;
/* start with lsb 6 bits of last */
last = ctl & SCOUTFS_BLOCK_MAPPING_MASK;
ctl >>= 6;
ctl_bits = 2;
prev = 0;
for (i = 0; i <= last; i++) {
if (ctl_bits == 0) {
if (size-- == 0)
return -EIO;
ctl = *(enc++);
ctl_bits = 8;
}
switch(ctl & SCOUTFS_BLOCK_ENC_MASK) {
case SCOUTFS_BLOCK_ENC_INC:
blkno = prev + 1;
break;
case SCOUTFS_BLOCK_ENC_OFFLINE:
set_bit(i, map->offline);
blkno = 0;
break;
case SCOUTFS_BLOCK_ENC_ZERO:
blkno = 0;
break;
case SCOUTFS_BLOCK_ENC_DELTA:
ret = zigzag_decode(&blkno, prev, enc, size);
/* XXX corruption, ran out of encoded bytes */
if (ret <= 0)
return -EIO;
enc += ret;
size -= ret;
break;
}
ctl >>= 2;
ctl_bits -= 2;
map->blknos[i] = blkno;
if (blkno)
prev = blkno;
}
/* XXX corruption: didn't use up all the bytes */
if (size != 0)
return -EIO;
return 0;
}
static void init_mapping_key(struct scoutfs_key *key, u64 ino, u64 iblock)
{
*key = (struct scoutfs_key) {
.sk_zone = SCOUTFS_FS_ZONE,
.skm_ino = cpu_to_le64(ino),
.sk_type = SCOUTFS_BLOCK_MAPPING_TYPE,
.skm_base = cpu_to_le64(iblock >> SCOUTFS_BLOCK_MAPPING_SHIFT),
};
}
static void init_free_key(struct scoutfs_key *key, u64 node_id, u64 full_bit,
u8 type)
{
*key = (struct scoutfs_key) {
.sk_zone = SCOUTFS_NODE_ZONE,
.skf_node_id = cpu_to_le64(node_id),
.sk_type = type,
.skf_base = cpu_to_le64(full_bit >> SCOUTFS_FREE_BITS_SHIFT),
};
}
/*
* Mark the given segno as allocated. We set its bit in a free segno
* item, possibly after creating it.
*/
static int set_segno_free(struct super_block *sb, u64 segno)
{
struct scoutfs_sb_info *sbi = SCOUTFS_SB(sb);
struct scoutfs_lock *lock = sbi->node_id_lock;
struct scoutfs_free_bits frb;
struct scoutfs_key key;
struct kvec val;
int bit = 0;
int ret;
init_free_key(&key, sbi->node_id, segno, SCOUTFS_FREE_BITS_SEGNO_TYPE);
kvec_init(&val, &frb, sizeof(struct scoutfs_free_bits));
ret = scoutfs_item_lookup_exact(sb, &key, &val, lock);
if (ret && ret != -ENOENT)
goto out;
bit = segno & SCOUTFS_FREE_BITS_MASK;
if (ret == -ENOENT) {
memset(&frb, 0, sizeof(frb));
set_bit_le(bit, &frb);
ret = scoutfs_item_create(sb, &key, &val, lock);
goto out;
}
if (test_and_set_bit_le(bit, frb.bits)) {
ret = -EIO;
goto out;
}
ret = scoutfs_item_update(sb, &key, &val, lock);
out:
trace_scoutfs_data_set_segno_free(sb, segno, le64_to_cpu(key.skf_base),
bit, ret);
return ret;
}
/*
* Create a new free blkno item with all but the given blkno marked
* free. We use the caller's key so they can delete it later if they
* need to.
*/
static int create_blkno_free(struct super_block *sb, u64 blkno,
struct scoutfs_key *key)
{
struct scoutfs_sb_info *sbi = SCOUTFS_SB(sb);
struct scoutfs_lock *lock = sbi->node_id_lock;
struct scoutfs_free_bits frb;
struct kvec val;
int bit;
init_free_key(key, sbi->node_id, blkno, SCOUTFS_FREE_BITS_BLKNO_TYPE);
kvec_init(&val, &frb, sizeof(struct scoutfs_free_bits));
bit = blkno & SCOUTFS_FREE_BITS_MASK;
memset(&frb, 0xff, sizeof(frb));
clear_bit_le(bit, frb.bits);
return scoutfs_item_create(sb, key, &val, lock);
}
/*
* Mark the first block in the segno as allocated. This isn't a general
* purpose bit clear. It knows that it's only called from allocation
* that found the bit so it won't create the segno item.
*
* And because it's allocating a block in the segno, it also has to
* create a free block item that marks the rest of the blknos in segno
* as free.
*
* It deletes the free segno item if it clears the last bit.
*/
static int clear_segno_free(struct super_block *sb, u64 segno)
{
struct scoutfs_sb_info *sbi = SCOUTFS_SB(sb);
struct scoutfs_lock *lock = sbi->node_id_lock;
struct scoutfs_free_bits frb;
struct scoutfs_key b_key;
struct scoutfs_key key;
struct kvec val;
u64 blkno;
int bit;
int ret;
init_free_key(&key, sbi->node_id, segno, SCOUTFS_FREE_BITS_SEGNO_TYPE);
kvec_init(&val, &frb, sizeof(struct scoutfs_free_bits));
ret = scoutfs_item_lookup_exact(sb, &key, &val, lock);
if (ret) {
/* XXX corruption, caller saw item.. should still exist */
if (ret == -ENOENT)
ret = -EIO;
goto out;
}
/* XXX corruption, bit couldn't have been set */
bit = segno & SCOUTFS_FREE_BITS_MASK;
if (!test_and_clear_bit_le(bit, frb.bits)) {
ret = -EIO;
goto out;
}
/* create the new blkno item, we can safely delete it */
blkno = segno << SCOUTFS_SEGMENT_BLOCK_SHIFT;
ret = create_blkno_free(sb, blkno, &b_key);
if (ret)
goto out;
if (bitmap_empty((long *)frb.bits, SCOUTFS_FREE_BITS_BITS))
ret = scoutfs_item_delete(sb, &key, lock);
else
ret = scoutfs_item_update(sb, &key, &val, lock);
if (ret)
scoutfs_item_delete_dirty(sb, &b_key);
out:
return ret;
}
/*
* Mark the given blkno free. Set its bit in its free blkno item,
* possibly after creating it. If all the bits are set we try to mark
* its segno free and delete the blkno item.
*/
static int set_blkno_free(struct super_block *sb, u64 blkno)
{
struct scoutfs_sb_info *sbi = SCOUTFS_SB(sb);
struct scoutfs_lock *lock = sbi->node_id_lock;
struct scoutfs_free_bits frb;
struct scoutfs_key key;
struct kvec val;
u64 segno;
int bit;
int ret;
/* get the specified item */
init_free_key(&key, sbi->node_id, blkno, SCOUTFS_FREE_BITS_BLKNO_TYPE);
kvec_init(&val, &frb, sizeof(struct scoutfs_free_bits));
ret = scoutfs_item_lookup_exact(sb, &key, &val, lock);
if (ret && ret != -ENOENT)
goto out;
bit = blkno & SCOUTFS_FREE_BITS_MASK;
if (ret == -ENOENT) {
memset(&frb, 0, sizeof(frb));
set_bit_le(bit, &frb);
ret = scoutfs_item_create(sb, &key, &val, lock);
goto out;
}
if (test_and_set_bit_le(bit, frb.bits)) {
ret = -EIO;
goto out;
}
if (!bitmap_full((long *)frb.bits, SCOUTFS_FREE_BITS_BITS)) {
ret = scoutfs_item_update(sb, &key, &val, lock);
goto out;
}
/* dirty so we can safely delete if set segno fails */
ret = scoutfs_item_dirty(sb, &key, lock);
if (ret)
goto out;
segno = blkno >> SCOUTFS_SEGMENT_BLOCK_SHIFT;
ret = set_segno_free(sb, segno);
if (ret)
goto out;
scoutfs_item_delete_dirty(sb, &key);
ret = 0;
out:
return ret;
}
/*
* Mark the given blkno as allocated. This is working on behalf of a
* caller who just saw the item, it must exist. We delete the free
* blkno item if all its bits are empty.
*/
static int clear_blkno_free(struct super_block *sb, u64 blkno)
{
struct scoutfs_sb_info *sbi = SCOUTFS_SB(sb);
struct scoutfs_lock *lock = sbi->node_id_lock;
struct scoutfs_free_bits frb;
struct scoutfs_key key;
struct kvec val;
int bit;
int ret;
/* get the specified item */
init_free_key(&key, sbi->node_id, blkno, SCOUTFS_FREE_BITS_BLKNO_TYPE);
kvec_init(&val, &frb, sizeof(struct scoutfs_free_bits));
ret = scoutfs_item_lookup_exact(sb, &key, &val, lock);
if (ret) {
/* XXX corruption, bits should have existed */
if (ret == -ENOENT)
ret = -EIO;
goto out;
}
/* XXX corruption, bit couldn't have been set */
bit = blkno & SCOUTFS_FREE_BITS_MASK;
if (!test_and_clear_bit_le(bit, frb.bits)) {
ret = -EIO;
goto out;
}
if (bitmap_empty((long *)frb.bits, SCOUTFS_FREE_BITS_BITS))
ret = scoutfs_item_delete(sb, &key, lock);
else
ret = scoutfs_item_update(sb, &key, &val, lock);
out:
return ret;
}
/*
* In each iteration iblock is the logical block and i is the index into
* blknos array and the bit in the offline bitmap. The iteration won't
* advance past the last logical block.
*/
#define for_each_block(i, iblock, last) \
for (i = iblock & SCOUTFS_BLOCK_MAPPING_MASK; \
i < SCOUTFS_BLOCK_MAPPING_BLOCKS && iblock <= (last); \
i++, iblock++)
#endif
static void init_file_extent_key(struct scoutfs_key *key, u64 ino, u64 last)
{
*key = (struct scoutfs_key) {
@@ -974,82 +491,6 @@ out:
return ret;
}
#if 0
/*
* Find the free bit item that contains the blkno and return the next blkno
* set starting with this blkno.
*
* Returns -ENOENT if there's no free blknos at or after the given blkno.
*/
static int find_free_blkno(struct super_block *sb, u64 blkno, u64 *blkno_ret)
{
struct scoutfs_sb_info *sbi = SCOUTFS_SB(sb);
struct scoutfs_lock *lock = sbi->node_id_lock;
struct scoutfs_free_bits frb;
struct scoutfs_key key;
struct kvec val;
int ret;
int bit;
init_free_key(&key, sbi->node_id, blkno, SCOUTFS_FREE_BITS_BLKNO_TYPE);
kvec_init(&val, &frb, sizeof(struct scoutfs_free_bits));
ret = scoutfs_item_lookup_exact(sb, &key, &val, lock);
if (ret < 0)
goto out;
bit = blkno & SCOUTFS_FREE_BITS_MASK;
bit = find_next_bit_le(frb.bits, SCOUTFS_FREE_BITS_BITS, bit);
if (bit >= SCOUTFS_FREE_BITS_BITS) {
ret = -ENOENT;
goto out;
}
*blkno_ret = (le64_to_cpu(key.skf_base) << SCOUTFS_FREE_BITS_SHIFT) +
bit;
ret = 0;
out:
return ret;
}
/*
* Find a free segno to satisfy allocation by finding the first bit set
* in the first free segno item.
*/
static int find_free_segno(struct super_block *sb, u64 *segno)
{
struct scoutfs_sb_info *sbi = SCOUTFS_SB(sb);
struct scoutfs_lock *lock = sbi->node_id_lock;
struct scoutfs_free_bits frb;
struct scoutfs_key last_key;
struct scoutfs_key key;
struct kvec val;
int bit;
int ret;
init_free_key(&key, sbi->node_id, 0, SCOUTFS_FREE_BITS_SEGNO_TYPE);
init_free_key(&last_key, sbi->node_id, U64_MAX,
SCOUTFS_FREE_BITS_SEGNO_TYPE);
kvec_init(&val, &frb, sizeof(struct scoutfs_free_bits));
ret = scoutfs_item_next(sb, &key, &last_key, &val, lock);
if (ret < 0)
goto out;
bit = find_next_bit_le(frb.bits, SCOUTFS_FREE_BITS_BITS, 0);
/* XXX corruption, shouldn't see empty items */
if (bit >= SCOUTFS_FREE_BITS_BITS) {
ret = -EIO;
goto out;
}
*segno = (le64_to_cpu(key.skf_base) << SCOUTFS_FREE_BITS_SHIFT) + bit;
ret = 0;
out:
return ret;
}
#endif
/*
* Allocate a single block for the logical block offset in the file.
* The caller tells us if the block was offline or not. We modify the
@@ -1412,61 +853,6 @@ static int scoutfs_write_end(struct file *file, struct address_space *mapping,
return ret;
}
struct pending_fiemap {
u64 logical;
u64 phys;
u64 size;
u32 flags;
};
#if 0
/*
* The caller is iterating over mapped blocks. We merge the current
* pending fiemap entry with the next block if we can. If we can't
* merge then we fill the current entry and start on the next. We also
* fill the pending mapping if the caller specifically tells us that
* this will be the last call.
*
* returns 0 to continue, 1 to stop, and -errno to stop with error.
*/
static int merge_or_fill(struct fiemap_extent_info *fieinfo,
struct pending_fiemap *pend, u64 logical, u64 phys,
bool offline, bool last)
{
u32 flags = offline ? FIEMAP_EXTENT_UNKNOWN : 0;
int ret;
/* merge if we can, returning if we don't have to fill last */
if (pend->logical + pend->size == logical &&
((pend->phys == 0 && phys == 0) ||
(pend->phys + pend->size == phys)) &&
pend->flags == flags) {
pend->size += SCOUTFS_BLOCK_SIZE;
if (!last)
return 0;
}
if (pend->size) {
if (last)
pend->flags |= FIEMAP_EXTENT_LAST;
/* returns 1 to end, including if we passed in _LAST */
ret = fiemap_fill_next_extent(fieinfo, pend->logical,
pend->phys, pend->size,
pend->flags);
if (ret != 0)
return ret;
}
pend->logical = logical;
pend->phys = phys;
pend->size = SCOUTFS_BLOCK_SIZE;
pend->flags = flags;
return 0;
}
#endif
/*
* Return all the file's extents whose blocks overlap with the caller's
* byte region. We set _LAST on the last extent and _UNKNOWN on offline
@@ -1614,122 +1000,3 @@ void scoutfs_data_destroy(struct super_block *sb)
kfree(datinf);
}
}
#if 0
/*
* Basic correctness tests of u64 and mapping encoding.
*/
int __init scoutfs_data_test(void)
{
u8 encoded[SCOUTFS_ZIGZAG_MAX_BYTES];
struct block_mapping *input;
struct block_mapping *output;
u64 blkno;
u8 bits;
u64 prev;
u64 in;
u64 out;
int ret;
int len;
int b;
int i;
prev = 0;
for (i = 0; i < 10000; i++) {
get_random_bytes_arch(&bits, sizeof(bits));
get_random_bytes_arch(&in, sizeof(in));
in &= (1ULL << (bits % 64)) - 1;
len = zigzag_encode(encoded, prev, in);
ret = zigzag_decode(&out, prev, encoded, len);
if (ret <= 0 || ret > SCOUTFS_ZIGZAG_MAX_BYTES || in != out) {
printk("i %d prev %llu in %llu out %llu len %d ret %d\n",
i, prev, in, out, len, ret);
ret = -EINVAL;
}
if (ret < 0)
return ret;
prev = out;
}
input = kmalloc(sizeof(struct block_mapping), GFP_KERNEL);
output = kmalloc(sizeof(struct block_mapping), GFP_KERNEL);
if (!input || !output) {
ret = -ENOMEM;
goto out;
}
for (i = 0; i < 1000; i++) {
prev = 0;
for (b = 0; b < SCOUTFS_BLOCK_MAPPING_BLOCKS; b++) {
if (b % (64 / 2) == 0)
get_random_bytes_arch(&in, sizeof(in));
clear_bit(b, input->offline);
switch(in & SCOUTFS_BLOCK_ENC_MASK) {
case SCOUTFS_BLOCK_ENC_INC:
blkno = prev + 1;
break;
case SCOUTFS_BLOCK_ENC_OFFLINE:
set_bit(b, input->offline);
blkno = 0;
break;
case SCOUTFS_BLOCK_ENC_ZERO:
blkno = 0;
break;
case SCOUTFS_BLOCK_ENC_DELTA:
get_random_bytes_arch(&bits, sizeof(bits));
get_random_bytes_arch(&blkno, sizeof(blkno));
blkno &= (1ULL << (bits % 64)) - 1;
break;
}
input->blknos[b] = blkno;
in >>= 2;
if (blkno)
prev = blkno;
}
len = encode_mapping(input);
if (len >= 1 && len < SCOUTFS_BLOCK_MAPPING_MAX_BYTES)
memcpy(output->encoded, input->encoded, len);
ret = decode_mapping(output, len);
if (ret) {
printk("map len %d decoding failed %d\n", len, ret);
ret = -EINVAL;
goto out;
}
for (b = 0; b < SCOUTFS_BLOCK_MAPPING_BLOCKS; b++) {
if (input->blknos[b] != output->blknos[b] ||
!!test_bit(b, input->offline) !=
!!test_bit(b, output->offline))
break;
}
if (b < SCOUTFS_BLOCK_MAPPING_BLOCKS) {
printk("map ind %u: in %llu %u, out %llu %u\n",
b, input->blknos[b],
!!test_bit(b, input->offline),
output->blknos[b],
!!test_bit(b, output->offline));
ret = -EINVAL;
goto out;
}
}
ret = 0;
out:
kfree(input);
kfree(output);
return ret;
}
#endif

View File

@@ -79,10 +79,6 @@ struct scoutfs_key {
#define skii_major _sk_second
#define skii_ino _sk_third
/* node free bit map */
#define skf_node_id _sk_first
#define skf_base _sk_second
/* node free extent */
#define sknf_node_id _sk_first
#define sknf_major _sk_second
@@ -110,10 +106,6 @@ struct scoutfs_key {
#define sks_ino _sk_first
#define sks_nr _sk_second
/* file data mapping */
#define skm_ino _sk_first
#define skm_base _sk_second
/* file extent */
#define skfe_ino _sk_first
#define skfe_last _sk_second
@@ -312,10 +304,8 @@ struct scoutfs_segment_block {
#define SCOUTFS_INODE_INDEX_NR 3 /* don't forget to update */
/* node zone */
#define SCOUTFS_FREE_BITS_SEGNO_TYPE 1
#define SCOUTFS_FREE_BITS_BLKNO_TYPE 2
#define SCOUTFS_FREE_EXTENT_BLKNO_TYPE 3
#define SCOUTFS_FREE_EXTENT_BLOCKS_TYPE 4
#define SCOUTFS_FREE_EXTENT_BLKNO_TYPE 1
#define SCOUTFS_FREE_EXTENT_BLOCKS_TYPE 2
/* fs zone */
#define SCOUTFS_INODE_TYPE 1
@@ -324,61 +314,11 @@ struct scoutfs_segment_block {
#define SCOUTFS_READDIR_TYPE 4
#define SCOUTFS_LINK_BACKREF_TYPE 5
#define SCOUTFS_SYMLINK_TYPE 6
#define SCOUTFS_BLOCK_MAPPING_TYPE 7
#define SCOUTFS_FILE_EXTENT_TYPE 7
#define SCOUTFS_ORPHAN_TYPE 8
#define SCOUTFS_FILE_EXTENT_TYPE 9
#define SCOUTFS_MAX_TYPE 16 /* power of 2 is efficient */
/* each mapping item describes a fixed number of blocks */
#define SCOUTFS_BLOCK_MAPPING_SHIFT 6
#define SCOUTFS_BLOCK_MAPPING_BLOCKS (1 << SCOUTFS_BLOCK_MAPPING_SHIFT)
#define SCOUTFS_BLOCK_MAPPING_MASK (SCOUTFS_BLOCK_MAPPING_BLOCKS - 1)
/*
* The mapping item value is a byte stream that encodes the value of the
* mapped blocks. The first byte contains the last index that contains
* a mapped block in its low bits. The high bits contain the control
* bits for the first (and possibly only) mapped block.
*
* From then on we consume the control bits in the current control byte
* for each mapped block. Each block has two bits that describe the
* block: zero, incremental from previous block, delta encoded, and
* offline. If we run out of control bits then we consume the next byte
* in the stream for additional control bits. If we have a delta
* encoded block then we consume its encoded bytes from the byte stream.
*/
#define SCOUTFS_BLOCK_ENC_ZERO 0
#define SCOUTFS_BLOCK_ENC_INC 1
#define SCOUTFS_BLOCK_ENC_DELTA 2
#define SCOUTFS_BLOCK_ENC_OFFLINE 3
#define SCOUTFS_BLOCK_ENC_MASK 3
#define SCOUTFS_ZIGZAG_MAX_BYTES (DIV_ROUND_UP(64, 7))
/*
* the largest block mapping has: nr byte, ctl bytes for all blocks, and
* worst case zigzag encodings for all blocks.
*/
#define SCOUTFS_BLOCK_MAPPING_MAX_BYTES \
(1 + (SCOUTFS_BLOCK_MAPPING_BLOCKS / 4) + \
(SCOUTFS_BLOCK_MAPPING_BLOCKS * SCOUTFS_ZIGZAG_MAX_BYTES))
/* free bit bitmaps contain a segment's worth of blocks */
#define SCOUTFS_FREE_BITS_SHIFT \
SCOUTFS_SEGMENT_BLOCK_SHIFT
#define SCOUTFS_FREE_BITS_BITS \
(1 << SCOUTFS_FREE_BITS_SHIFT)
#define SCOUTFS_FREE_BITS_MASK \
(SCOUTFS_FREE_BITS_BITS - 1)
#define SCOUTFS_FREE_BITS_U64S \
DIV_ROUND_UP(SCOUTFS_FREE_BITS_BITS, 64)
struct scoutfs_free_bits {
__le64 bits[SCOUTFS_FREE_BITS_U64S];
} __packed;
/*
* File extents have more data than easily fits in the key so we move
* the non-indexed fields into the value.

View File

@@ -26,8 +26,6 @@ char *scoutfs_zone_strings[SCOUTFS_MAX_ZONE] = {
char *scoutfs_type_strings[SCOUTFS_MAX_ZONE][SCOUTFS_MAX_TYPE] = {
[SCOUTFS_INODE_INDEX_ZONE][SCOUTFS_INODE_INDEX_META_SEQ_TYPE] = "msq",
[SCOUTFS_INODE_INDEX_ZONE][SCOUTFS_INODE_INDEX_DATA_SEQ_TYPE] = "dsq",
[SCOUTFS_NODE_ZONE][SCOUTFS_FREE_BITS_SEGNO_TYPE] = "fsg",
[SCOUTFS_NODE_ZONE][SCOUTFS_FREE_BITS_BLKNO_TYPE] = "fbk",
[SCOUTFS_NODE_ZONE][SCOUTFS_FREE_EXTENT_BLKNO_TYPE] = "fbn",
[SCOUTFS_NODE_ZONE][SCOUTFS_FREE_EXTENT_BLOCKS_TYPE] = "fbs",
[SCOUTFS_NODE_ZONE][SCOUTFS_ORPHAN_TYPE] = "orp",
@@ -37,7 +35,6 @@ char *scoutfs_type_strings[SCOUTFS_MAX_ZONE][SCOUTFS_MAX_TYPE] = {
[SCOUTFS_FS_ZONE][SCOUTFS_READDIR_TYPE] = "rdr",
[SCOUTFS_FS_ZONE][SCOUTFS_LINK_BACKREF_TYPE] = "lbr",
[SCOUTFS_FS_ZONE][SCOUTFS_SYMLINK_TYPE] = "sym",
[SCOUTFS_FS_ZONE][SCOUTFS_BLOCK_MAPPING_TYPE] = "bmp",
[SCOUTFS_FS_ZONE][SCOUTFS_FILE_EXTENT_TYPE] = "fex",
};

View File

@@ -526,32 +526,6 @@ TRACE_EVENT(scoutfs_data_truncate_items,
__entry->iblock, __entry->last, __entry->offline)
);
TRACE_EVENT(scoutfs_data_set_segno_free,
TP_PROTO(struct super_block *sb, __u64 segno, __u64 base,
unsigned int bit, int ret),
TP_ARGS(sb, segno, base, bit, ret),
TP_STRUCT__entry(
__field(__u64, fsid)
__field(__u64, segno)
__field(__u64, base)
__field(unsigned int, bit)
__field(int, ret)
),
TP_fast_assign(
__entry->fsid = FSID_ARG(sb);
__entry->segno = segno;
__entry->base = base;
__entry->bit = bit;
__entry->ret = ret;
),
TP_printk(FSID_FMT" segno %llu base %llu bit %u ret %d", __entry->fsid,
__entry->segno, __entry->base, __entry->bit, __entry->ret)
);
TRACE_EVENT(scoutfs_sync_fs,
TP_PROTO(struct super_block *sb, int wait),