diff --git a/kmod/src/format.h b/kmod/src/format.h index c2b938d7..300a1a46 100644 --- a/kmod/src/format.h +++ b/kmod/src/format.h @@ -327,7 +327,9 @@ struct scoutfs_alloc_root { #define SCOUTFS_ALLOC_OWNER_SRCH 3 struct scoutfs_mounted_client_btree_val { + union scoutfs_inet_addr addr; __u8 flags; + __u8 __pad[7]; }; #define SCOUTFS_MOUNTED_CLIENT_QUORUM (1 << 0) diff --git a/kmod/src/net.h b/kmod/src/net.h index e16ec524..847e9204 100644 --- a/kmod/src/net.h +++ b/kmod/src/net.h @@ -100,6 +100,16 @@ static inline void scoutfs_addr_to_sin(struct sockaddr_in *sin, sin->sin_port = cpu_to_be16(le16_to_cpu(addr->v4.port)); } +static inline void scoutfs_sin_to_addr(union scoutfs_inet_addr *addr, struct sockaddr_in *sin) +{ + BUG_ON(sin->sin_family != AF_INET); + + memset(addr, 0, sizeof(union scoutfs_inet_addr)); + addr->v4.family = cpu_to_le16(SCOUTFS_AF_IPV4); + addr->v4.addr = be32_to_le32(sin->sin_addr.s_addr); + addr->v4.port = be16_to_le16(sin->sin_port); +} + struct scoutfs_net_connection * scoutfs_net_alloc_conn(struct super_block *sb, scoutfs_net_notify_t notify_up, diff --git a/kmod/src/server.c b/kmod/src/server.c index cbb23088..872d5339 100644 --- a/kmod/src/server.c +++ b/kmod/src/server.c @@ -1453,14 +1453,19 @@ static void init_mounted_client_key(struct scoutfs_key *key, u64 rid) }; } +static bool invalid_mounted_client_item(struct scoutfs_btree_item_ref *iref) +{ + return (iref->val_len != sizeof(struct scoutfs_mounted_client_btree_val)); +} + /* * Insert a new mounted client item for a client that is sending us a * greeting that hasn't yet seen a response. The greeting can be * retransmitted to a new server after the previous inserted the item so * it's acceptable to see -EEXIST. */ -static int insert_mounted_client(struct super_block *sb, u64 rid, - u64 gr_flags) +static int insert_mounted_client(struct super_block *sb, u64 rid, u64 gr_flags, + struct sockaddr_in *sin) { DECLARE_SERVER_INFO(sb, server); struct scoutfs_super_block *super = &SCOUTFS_SB(sb)->super; @@ -1469,6 +1474,7 @@ static int insert_mounted_client(struct super_block *sb, u64 rid, int ret; init_mounted_client_key(&key, rid); + scoutfs_sin_to_addr(&mcv.addr, sin); mcv.flags = 0; if (gr_flags & SCOUTFS_NET_GREETING_FLAG_QUORUM) mcv.flags |= SCOUTFS_MOUNTED_CLIENT_QUORUM; @@ -1484,6 +1490,34 @@ static int insert_mounted_client(struct super_block *sb, u64 rid, return ret; } +static int lookup_mounted_client_addr(struct super_block *sb, u64 rid, + union scoutfs_inet_addr *addr) +{ + DECLARE_SERVER_INFO(sb, server); + struct scoutfs_super_block *super = &SCOUTFS_SB(sb)->super; + struct scoutfs_mounted_client_btree_val *mcv; + SCOUTFS_BTREE_ITEM_REF(iref); + struct scoutfs_key key; + int ret; + + init_mounted_client_key(&key, rid); + + mutex_lock(&server->mounted_clients_mutex); + ret = scoutfs_btree_lookup(sb, &super->mounted_clients, &key, &iref); + if (ret == 0) { + if (invalid_mounted_client_item(&iref)) { + ret = -EIO; + } else { + mcv = iref.val; + *addr = mcv->addr; + } + scoutfs_btree_put_iref(&iref); + } + mutex_unlock(&server->mounted_clients_mutex); + + return ret; +} + /* * Remove the record of a mounted client. The record can already be * removed if we're processing a farewell on behalf of a client that @@ -1622,8 +1656,8 @@ static int server_greeting(struct super_block *sb, if (ret < 0) goto send_err; - ret = insert_mounted_client(sb, le64_to_cpu(gr->rid), - le64_to_cpu(gr->flags)); + ret = insert_mounted_client(sb, le64_to_cpu(gr->rid), le64_to_cpu(gr->flags), + &conn->peername); ret = scoutfs_server_apply_commit(sb, ret); queue_work(server->wq, &server->farewell_work); @@ -1680,11 +1714,6 @@ struct farewell_request { u64 rid; }; -static bool invalid_mounted_client_item(struct scoutfs_btree_item_ref *iref) -{ - return (iref->val_len != - sizeof(struct scoutfs_mounted_client_btree_val)); -} /* * Reclaim all the resources for a mount which has gone away. It's sent @@ -2040,20 +2069,30 @@ static void fence_pending_recov_worker(struct work_struct *work) struct server_info *server = container_of(work, struct server_info, fence_pending_recov_work); struct super_block *sb = server->sb; + union scoutfs_inet_addr addr; u64 rid = 0; - int ret; + int ret = 0; while ((rid = scoutfs_recov_next_pending(sb, rid, SCOUTFS_RECOV_ALL)) > 0) { scoutfs_err(sb, "%lu ms recovery timeout expired for client rid %016llx, fencing", SERVER_RECOV_TIMEOUT_MS, rid); - ret = scoutfs_fence_start(sb, rid, 0, SCOUTFS_FENCE_CLIENT_RECOVERY); - if (ret) { + ret = lookup_mounted_client_addr(sb, rid, &addr); + if (ret < 0) { + scoutfs_err(sb, "client rid addr lookup err %d, shutting down server", ret); + break; + } + + ret = scoutfs_fence_start(sb, rid, le32_to_be32(addr.v4.addr), + SCOUTFS_FENCE_CLIENT_RECOVERY); + if (ret < 0) { scoutfs_err(sb, "fence returned err %d, shutting down server", ret); - scoutfs_server_abort(sb); break; } } + + if (ret < 0) + scoutfs_server_abort(sb); } static void recovery_timeout(struct super_block *sb) diff --git a/utils/src/print.c b/utils/src/print.c index 9ddc3e4b..e61361bd 100644 --- a/utils/src/print.c +++ b/utils/src/print.c @@ -372,9 +372,13 @@ static int print_mounted_client_entry(struct scoutfs_key *key, void *val, unsigned val_len, void *arg) { struct scoutfs_mounted_client_btree_val *mcv = val; + struct in_addr in; - printf(" rid %016llx flags 0x%x\n", - le64_to_cpu(key->skmc_rid), mcv->flags); + memset(&in, 0, sizeof(in)); + in.s_addr = htonl(le32_to_cpu(mcv->addr.v4.addr)); + + printf(" rid %016llx ipv4_addr %s flags 0x%x\n", + le64_to_cpu(key->skmc_rid), inet_ntoa(in), mcv->flags); return 0; }