scoutfs-utils: support file and node free extents

Add support for printing the items used to track file mapping extents
and free extents.

Signed-off-by: Zach Brown <zab@versity.com>
This commit is contained in:
Zach Brown
2018-04-06 15:38:28 -07:00
committed by Zach Brown
parent f649edd65d
commit 35e4ab92f0
3 changed files with 46 additions and 81 deletions

View File

@@ -15,6 +15,7 @@
#define SCOUTFS_BLOCKS_PER_PAGE (PAGE_SIZE / SCOUTFS_BLOCK_SIZE)
#define SCOUTFS_BLOCK_SECTOR_SHIFT (SCOUTFS_BLOCK_SHIFT - 9)
#define SCOUTFS_BLOCK_SECTORS (1 << SCOUTFS_BLOCK_SECTOR_SHIFT)
#define SCOUTFS_BLOCK_MAX (U64_MAX >> SCOUTFS_BLOCK_SHIFT)
/*
* FS data is stored in segments, for now they're fixed size. They'll
@@ -78,9 +79,10 @@ 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
#define sknf_minor _sk_third
/* node orphan inode */
#define sko_node_id _sk_first
@@ -104,9 +106,9 @@ 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
/*
* The btree still uses memcmp() to compare keys. We should fix that
@@ -302,8 +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 1
#define SCOUTFS_FREE_EXTENT_BLOCKS_TYPE 2
/* fs zone */
#define SCOUTFS_INODE_TYPE 1
@@ -312,60 +314,23 @@ 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_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.
* File extents have more data than easily fits in the key so we move
* the non-indexed fields into the value.
*/
#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];
struct scoutfs_file_extent {
__le64 blkno;
__le64 len;
__u8 flags;
} __packed;
#define SEF_OFFLINE 0x1
/*
* The first xattr part item has a header that describes the xattr. The
* name and value are then packed into the following bytes in the first
@@ -509,7 +474,6 @@ enum {
SCOUTFS_DT_WHT,
};
#define SCOUTFS_MAX_VAL_SIZE SCOUTFS_BLOCK_MAPPING_MAX_BYTES
#define SCOUTFS_XATTR_MAX_NAME_LEN 255
#define SCOUTFS_XATTR_MAX_VAL_LEN 65535
@@ -519,6 +483,8 @@ enum {
DIV_ROUND_UP(sizeof(struct scoutfs_xattr) + name_len + val_len, \
SCOUTFS_XATTR_MAX_PART_SIZE);
#define SCOUTFS_MAX_VAL_SIZE SCOUTFS_XATTR_MAX_PART_SIZE
/*
* structures used by dlm
*/

View File

@@ -28,8 +28,8 @@ 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",
[SCOUTFS_FS_ZONE][SCOUTFS_INODE_TYPE] = "ino",
[SCOUTFS_FS_ZONE][SCOUTFS_XATTR_TYPE] = "xat",
@@ -37,7 +37,7 @@ 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",
};
char scoutfs_unknown_u8_strings[U8_MAX][U8_STR_MAX];

View File

@@ -161,30 +161,30 @@ static void print_symlink(struct scoutfs_key *key, void *val, int val_len)
le64_to_cpu(key->sks_ino), le64_to_cpu(key->sks_nr), name);
}
/*
* XXX not decoding the bytes yet
*/
static void print_block_mapping(struct scoutfs_key *key, void *val, int val_len)
static void print_file_extent(struct scoutfs_key *key, void *val, int val_len)
{
u64 blk_off = le64_to_cpu(key->skm_base) << SCOUTFS_BLOCK_MAPPING_SHIFT;
u8 nr = *((u8 *)val) & 63;
struct scoutfs_file_extent *fex = val;
u64 iblock = le64_to_cpu(key->skfe_last) - le64_to_cpu(fex->len) + 1;
printf(" block mapping: ino %llu blk_off %llu blocks %u\n",
le64_to_cpu(key->skm_ino), blk_off, nr);
printf(" extent: ino %llu (last %llu) iblock %llu len %llu "
"blkno %llu flags 0x%x\n",
le64_to_cpu(key->skfe_ino), le64_to_cpu(key->skfe_last),
iblock, le64_to_cpu(fex->len), le64_to_cpu(fex->blkno),
fex->flags);
}
static void print_free_bits(struct scoutfs_key *key, void *val, int val_len)
static void print_free_extent(struct scoutfs_key *key, void *val, int val_len)
{
struct scoutfs_free_bits *frb = val;
int i;
u64 start = le64_to_cpu(key->sknf_major);
u64 len = le64_to_cpu(key->sknf_minor);
if (key->sk_type == SCOUTFS_FREE_EXTENT_BLOCKS_TYPE)
swap(start, len);
start -= (len - 1);
printf(" node_id %llx base %llu\n",
le64_to_cpu(key->skf_node_id), le64_to_cpu(key->skf_base));
printf(" bits:");
for (i = 0; i < array_size(frb->bits); i++)
printf(" %016llx", le64_to_cpu(frb->bits[i]));
printf("\n");
printf(" free extent: major %llu minor %llu (start %llu "
"len %llu)\n",
le64_to_cpu(key->sknf_major), le64_to_cpu(key->sknf_minor),
start, len);
}
static void print_inode_index(struct scoutfs_key *key, void *val, int val_len)
@@ -203,9 +203,9 @@ static print_func_t find_printer(u8 zone, u8 type)
return print_inode_index;
if (zone == SCOUTFS_NODE_ZONE) {
if (type == SCOUTFS_FREE_BITS_SEGNO_TYPE ||
type == SCOUTFS_FREE_BITS_BLKNO_TYPE)
return print_free_bits;
if (type == SCOUTFS_FREE_EXTENT_BLKNO_TYPE ||
type == SCOUTFS_FREE_EXTENT_BLOCKS_TYPE)
return print_free_extent;
if (type == SCOUTFS_ORPHAN_TYPE)
return print_orphan;
}
@@ -218,8 +218,7 @@ static print_func_t find_printer(u8 zone, u8 type)
case SCOUTFS_READDIR_TYPE: return print_dirent;
case SCOUTFS_SYMLINK_TYPE: return print_symlink;
case SCOUTFS_LINK_BACKREF_TYPE: return print_dirent;
case SCOUTFS_BLOCK_MAPPING_TYPE:
return print_block_mapping;
case SCOUTFS_FILE_EXTENT_TYPE: return print_file_extent;
}
}