scoutfs-utils: sort keys by zones, then types

Our item cache protocol is tied to holding DLM locks which cover a
region of the item namespace.  We want locks to cover all the data
associated with an inode and other locks to cover the indexes.  So we
resort the items first by major (index, fs) then by inode type (inode,
dirent, etc).

Signed-off-by: Zach Brown <zab@versity.com>
This commit is contained in:
Zach Brown
2017-07-19 10:33:12 -07:00
parent 6c37e3dee0
commit 7bbe49fde2
4 changed files with 280 additions and 189 deletions
+73 -52
View File
@@ -50,12 +50,6 @@ struct scoutfs_block_header {
__le64 blkno;
} __packed;
/*
* The largest possible btree has 2^64 bytes worth of segments with
* the largest possible keys in a pathologically sparse btree where
* all the nodes are half full.
*/
/*
* Assert that we'll be able to represent all possible keys with 8 64bit
* primary sort values.
@@ -94,9 +88,6 @@ enum {
SCOUTFS_BTREE_BIT_HALF2 = (1 << 1),
};
#define SCOUTFS_BTREE_HALF_BITS \
(SCOUTFS_BTREE_BIT_HALF1 | SCOUTFS_BTREE_BIT_HALF2)
struct scoutfs_btree_ref {
__le64 blkno;
__le64 seq;
@@ -165,9 +156,8 @@ struct scoutfs_manifest {
* segment key in the manifest btree key. Both of their keys are in the
* value.
*
* Level 1 segments are sorted by their key before their seq so the
* btree header has the key and the seq is in the footer. Only their
* last key is in the value.
* Level 1 segments are sorted by their first key so their last key is
* in the value.
*
* We go to all this trouble so that we can communicate a version of the
* manifest with one btree root, have dense btree keys which are used as
@@ -246,73 +236,78 @@ struct scoutfs_segment_block {
} __packed;
/*
* Currently we sort keys by the numeric value of the types, but that
* isn't necessary. We could have an arbitrary sort order. So we don't
* have to stress about cleverly allocating the types.
* Keys are first sorted by major key zones.
*/
#define SCOUTFS_INODE_KEY 1
#define SCOUTFS_XATTR_KEY 3
#define SCOUTFS_DIRENT_KEY 5
#define SCOUTFS_READDIR_KEY 6
#define SCOUTFS_LINK_BACKREF_KEY 7
#define SCOUTFS_SYMLINK_KEY 8
#define SCOUTFS_FILE_EXTENT_KEY 9
#define SCOUTFS_ORPHAN_KEY 10
#define SCOUTFS_FREE_EXTENT_BLKNO_KEY 11
#define SCOUTFS_FREE_EXTENT_BLOCKS_KEY 12
#define SCOUTFS_INODE_INDEX_CTIME_KEY 13 /* don't forget first and last */
#define SCOUTFS_INODE_INDEX_MTIME_KEY 14
#define SCOUTFS_INODE_INDEX_SIZE_KEY 15
#define SCOUTFS_INODE_INDEX_META_SEQ_KEY 16
#define SCOUTFS_INODE_INDEX_DATA_SEQ_KEY 17
/* not found in the fs */
#define SCOUTFS_MAX_UNUSED_KEY 253
#define SCOUTFS_NET_ADDR_KEY 254
#define SCOUTFS_NET_LISTEN_KEY 255
#define SCOUTFS_INODE_INDEX_ZONE 1
#define SCOUTFS_NODE_ZONE 2
#define SCOUTFS_FS_ZONE 3
/* inode index zone */
#define SCOUTFS_INODE_INDEX_CTIME_TYPE 1
#define SCOUTFS_INODE_INDEX_MTIME_TYPE 2
#define SCOUTFS_INODE_INDEX_SIZE_TYPE 3
#define SCOUTFS_INODE_INDEX_META_SEQ_TYPE 4
#define SCOUTFS_INODE_INDEX_DATA_SEQ_TYPE 5
#define SCOUTFS_INODE_INDEX_FIRST SCOUTFS_INODE_INDEX_CTIME_KEY
#define SCOUTFS_INODE_INDEX_LAST SCOUTFS_INODE_INDEX_DATA_SEQ_KEY
#define SCOUTFS_INODE_INDEX_NR \
(SCOUTFS_INODE_INDEX_LAST - SCOUTFS_INODE_INDEX_FIRST + 1)
(SCOUTFS_INODE_INDEX_DATA_SEQ_TYPE - SCOUTFS_INODE_INDEX_CTIME_TYPE + 1)
/* node zone */
#define SCOUTFS_FREE_EXTENT_BLKNO_TYPE 11
#define SCOUTFS_FREE_EXTENT_BLOCKS_TYPE 12
/* fs zone */
#define SCOUTFS_INODE_TYPE 1
#define SCOUTFS_XATTR_TYPE 2
#define SCOUTFS_DIRENT_TYPE 3
#define SCOUTFS_READDIR_TYPE 4
#define SCOUTFS_LINK_BACKREF_TYPE 5
#define SCOUTFS_SYMLINK_TYPE 6
#define SCOUTFS_FILE_EXTENT_TYPE 7
#define SCOUTFS_ORPHAN_TYPE 8
/* XXX don't need these now that we have dlm lock spaces and resources */
#define SCOUTFS_NET_ADDR_TYPE 254
#define SCOUTFS_NET_LISTEN_TYPE 255
/* value is struct scoutfs_inode */
struct scoutfs_inode_key {
__u8 type;
__u8 zone;
__be64 ino;
__u8 type;
} __packed;
/* value is struct scoutfs_dirent without the name */
struct scoutfs_dirent_key {
__u8 type;
__u8 zone;
__be64 ino;
__u8 type;
__u8 name[0];
} __packed;
/* value is struct scoutfs_dirent with the name */
struct scoutfs_readdir_key {
__u8 type;
__u8 zone;
__be64 ino;
__u8 type;
__be64 pos;
} __packed;
/* value is empty */
struct scoutfs_link_backref_key {
__u8 type;
__u8 zone;
__be64 ino;
__u8 type;
__be64 dir_ino;
__u8 name[0];
} __packed;
/* no value */
struct scoutfs_orphan_key {
__u8 type;
__be64 ino;
} __packed;
/* no value */
struct scoutfs_file_extent_key {
__u8 type;
__u8 zone;
__be64 ino;
__u8 type;
__be64 last_blk_off;
__be64 last_blkno;
__be64 blocks;
@@ -323,23 +318,34 @@ struct scoutfs_file_extent_key {
/* no value */
struct scoutfs_free_extent_blkno_key {
__u8 type;
__u8 zone;
__be64 node_id;
__u8 type;
__be64 last_blkno;
__be64 blocks;
} __packed;
struct scoutfs_free_extent_blocks_key {
__u8 type;
__u8 zone;
__be64 node_id;
__u8 type;
__be64 blocks;
__be64 last_blkno;
} __packed;
/* value is each item's part of the full xattr value for the off/len */
struct scoutfs_xattr_key {
/* no value */
struct scoutfs_orphan_key {
__u8 zone;
__be64 node_id;
__u8 type;
__be64 ino;
} __packed;
/* value is each item's part of the full xattr value for the off/len */
struct scoutfs_xattr_key {
__u8 zone;
__be64 ino;
__u8 type;
__u8 name[0];
} __packed;
@@ -355,8 +361,9 @@ struct scoutfs_xattr_val_header {
/* size determines nr needed to store full target path in their values */
struct scoutfs_symlink_key {
__u8 type;
__u8 zone;
__be64 ino;
__u8 type;
__u8 nr;
} __packed;
@@ -366,6 +373,7 @@ struct scoutfs_betimespec {
} __packed;
struct scoutfs_inode_index_key {
__u8 zone;
__u8 type;
__be64 major;
__be32 minor;
@@ -498,6 +506,19 @@ enum {
#define SCOUTFS_XATTR_MAX_PARTS \
DIV_ROUND_UP(SCOUTFS_XATTR_MAX_SIZE, SCOUTFS_XATTR_PART_SIZE)
/*
* structures used by dlm
*/
struct scoutfs_lock_name {
__u8 zone;
__u8 type;
__le64 first;
__le64 second;
} __packed;
#define SCOUTFS_LOCK_INODE_GROUP_NR 1024
#define SCOUTFS_LOCK_INODE_GROUP_MASK (SCOUTFS_LOCK_INODE_GROUP_NR - 1)
#define SCOUTFS_LOCK_INODE_GROUP_OFFSET (~0ULL)
/*
* messages over the wire.