mirror of
https://github.com/versity/scoutfs.git
synced 2026-06-06 11:42:35 +00:00
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:
@@ -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
|
||||
*/
|
||||
|
||||
@@ -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];
|
||||
|
||||
@@ -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;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
Reference in New Issue
Block a user