From 514418421cef26f182fbf035d255b8bf87dd9791 Mon Sep 17 00:00:00 2001 From: Zach Brown Date: Mon, 8 Apr 2019 13:05:10 -0700 Subject: [PATCH] scoutfs-utils: add support for unmount_barrier Signed-off-by: Zach Brown --- utils/src/format.h | 28 +++++++++++++++++++++++++++- utils/src/print.c | 27 ++++++++++++++++++++++++++- 2 files changed, 53 insertions(+), 2 deletions(-) diff --git a/utils/src/format.h b/utils/src/format.h index 6918bd82..b5ced5d4 100644 --- a/utils/src/format.h +++ b/utils/src/format.h @@ -48,6 +48,8 @@ #define SCOUTFS_QUORUM_BLOCKS ((128ULL * 1024) >> SCOUTFS_BLOCK_SHIFT) #define SCOUTFS_QUORUM_MAX_SLOTS SCOUTFS_QUORUM_BLOCKS +#define SCOUTFS_UNIQUE_NAME_MAX_BYTES 64 /* includes null */ + /* * Base types used by other structures. */ @@ -289,6 +291,18 @@ struct scoutfs_trans_seq_btree_key { __be64 node_id; } __packed; +/* + * The server keeps a persistent record of mounted clients. + */ +struct scoutfs_mounted_client_btree_key { + __be64 node_id; +} __packed; + +struct scoutfs_mounted_client_btree_val { + __u8 name[SCOUTFS_UNIQUE_NAME_MAX_BYTES]; +} __packed; + + /* * The max number of links defines the max number of entries that we can * index in o(log n) and the static list head storage size in the @@ -395,7 +409,6 @@ struct scoutfs_xattr { #define member_sizeof(TYPE, MEMBER) (sizeof(((TYPE *)0)->MEMBER)) #define SCOUTFS_UUID_BYTES 16 -#define SCOUTFS_UNIQUE_NAME_MAX_BYTES 64 /* includes null */ /* * During each quorum voting interval the fabric has to process 2 reads @@ -418,6 +431,7 @@ struct scoutfs_xattr { * @config_gen: references the config gen in the super block * @write_nr: incremented for every write, only 0 when never written * @elected_nr: incremented when elected, 0 otherwise + * @unmount_barrier: incremented by servers when all members have unmounted * @vote_slot: the active config slot that the writer is voting for */ struct scoutfs_quorum_block { @@ -426,6 +440,7 @@ struct scoutfs_quorum_block { __le64 config_gen; __le64 write_nr; __le64 elected_nr; + __le64 unmount_barrier; __le32 crc; __u8 vote_slot; } __packed; @@ -475,6 +490,7 @@ struct scoutfs_super_block { struct scoutfs_quorum_config quorum_config; struct scoutfs_btree_root lock_clients; struct scoutfs_btree_root trans_seqs; + struct scoutfs_btree_root mounted_clients; } __packed; #define SCOUTFS_ROOT_INO 1 @@ -593,20 +609,30 @@ enum { * Greetings verify identity of communicating nodes. The sender sends * their credentials and the receiver verifies them. * + * @name: The client sends its unique name to the server. + * * @server_term: The raft term that elected the server. Initially 0 * from the client, sent by the server, then sent by the client as it * tries to reconnect. Used to identify a client reconnecting to a * server that has timed out its connection. * + * @unmount_barrier: Incremented every time the remaining majority of + * quorum members all agree to leave. The server tells a quorum member + * the value that it's connecting under so that if the client sees the + * value increase in a quorum block it knows that the server has + * processed its farewell and can safely unmount. + * * @node_id: The id of the client. Initially 0 from the client, * assigned by the server, and sent by the client as it reconnects. * Used by the server to identify reconnecting clients whose existing * state must be dealt with. */ struct scoutfs_net_greeting { + __u8 name[SCOUTFS_UNIQUE_NAME_MAX_BYTES]; __le64 fsid; __le64 format_hash; __le64 server_term; + __le64 unmount_barrier; __le64 node_id; __le64 flags; } __packed; diff --git a/utils/src/print.c b/utils/src/print.c index 14aeac14..7f55c648 100644 --- a/utils/src/print.c +++ b/utils/src/print.c @@ -364,6 +364,19 @@ static int print_trans_seqs_entry(void *key, unsigned key_len, void *val, return 0; } +/* XXX should make sure that the val is null terminated */ +static int print_mounted_client_entry(void *key, unsigned key_len, void *val, + unsigned val_len, void *arg) +{ + struct scoutfs_mounted_client_btree_key *mck = key; + struct scoutfs_mounted_client_btree_val *mcv = val; + + printf(" node_id %llu name %s\n", + be64_to_cpu(mck->node_id), mcv->name); + + return 0; +} + typedef int (*print_item_func)(void *key, unsigned key_len, void *val, unsigned val_len, void *arg); @@ -483,13 +496,15 @@ static int print_quorum_blocks(int fd, struct scoutfs_super_block *super) if (blk->fsid != 0 || blk->write_nr != 0) { printf("quorum block blkno %llu\n" " fsid %llx blkno %llu config_gen %llu crc 0x%08x\n" - " write_nr %llu elected_nr %llu vote_slot %u\n", + " write_nr %llu elected_nr %llu " + "unmount_barrier %llu vote_slot %u\n", blkno, le64_to_cpu(blk->fsid), le64_to_cpu(blk->blkno), le64_to_cpu(blk->config_gen), le32_to_cpu(blk->crc), le64_to_cpu(blk->write_nr), le64_to_cpu(blk->elected_nr), + le64_to_cpu(blk->unmount_barrier), blk->vote_slot); } @@ -544,6 +559,7 @@ static void print_super_block(struct scoutfs_super_block *super, u64 blkno) " btree ring: first_blkno %llu nr_blocks %llu next_block %llu " "next_seq %llu\n" " lock_clients root: height %u blkno %llu seq %llu mig_len %u\n" + " mounted_clients root: height %u blkno %llu seq %llu mig_len %u\n" " trans_seqs root: height %u blkno %llu seq %llu mig_len %u\n" " alloc btree root: height %u blkno %llu seq %llu mig_len %u\n" " manifest btree root: height %u blkno %llu seq %llu mig_len %u\n", @@ -563,6 +579,10 @@ static void print_super_block(struct scoutfs_super_block *super, u64 blkno) le64_to_cpu(super->lock_clients.ref.blkno), le64_to_cpu(super->lock_clients.ref.seq), le16_to_cpu(super->lock_clients.migration_key_len), + super->mounted_clients.height, + le64_to_cpu(super->mounted_clients.ref.blkno), + le64_to_cpu(super->mounted_clients.ref.seq), + le16_to_cpu(super->mounted_clients.migration_key_len), super->trans_seqs.height, le64_to_cpu(super->trans_seqs.ref.blkno), le64_to_cpu(super->trans_seqs.ref.seq), @@ -631,6 +651,11 @@ static int print_volume(int fd) if (err && !ret) ret = err; + err = print_btree(fd, super, "mounted_clients", &super->mounted_clients, + print_mounted_client_entry, NULL); + if (err && !ret) + ret = err; + err = print_btree(fd, super, "trans_seqs", &super->trans_seqs, print_trans_seqs_entry, NULL); if (err && !ret)