18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * fs/hmdfs/comm/connection.c 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Copyright (c) 2020-2021 Huawei Device Co., Ltd. 68c2ecf20Sopenharmony_ci */ 78c2ecf20Sopenharmony_ci 88c2ecf20Sopenharmony_ci#include "connection.h" 98c2ecf20Sopenharmony_ci 108c2ecf20Sopenharmony_ci#include <linux/file.h> 118c2ecf20Sopenharmony_ci#include <linux/freezer.h> 128c2ecf20Sopenharmony_ci#include <linux/fs.h> 138c2ecf20Sopenharmony_ci#include <linux/kthread.h> 148c2ecf20Sopenharmony_ci#include <linux/module.h> 158c2ecf20Sopenharmony_ci#include <linux/net.h> 168c2ecf20Sopenharmony_ci#include <linux/tcp.h> 178c2ecf20Sopenharmony_ci#include <linux/workqueue.h> 188c2ecf20Sopenharmony_ci 198c2ecf20Sopenharmony_ci#include "device_node.h" 208c2ecf20Sopenharmony_ci#include "hmdfs.h" 218c2ecf20Sopenharmony_ci#include "message_verify.h" 228c2ecf20Sopenharmony_ci#include "node_cb.h" 238c2ecf20Sopenharmony_ci#include "protocol.h" 248c2ecf20Sopenharmony_ci#include "socket_adapter.h" 258c2ecf20Sopenharmony_ci 268c2ecf20Sopenharmony_ci#ifdef CONFIG_HMDFS_FS_ENCRYPTION 278c2ecf20Sopenharmony_ci#include "crypto.h" 288c2ecf20Sopenharmony_ci#endif 298c2ecf20Sopenharmony_ci 308c2ecf20Sopenharmony_ci#define HMDFS_WAIT_REQUEST_END_MIN 20 318c2ecf20Sopenharmony_ci#define HMDFS_WAIT_REQUEST_END_MAX 30 328c2ecf20Sopenharmony_ci 338c2ecf20Sopenharmony_ci#define HMDFS_WAIT_CONN_RELEASE (3 * HZ) 348c2ecf20Sopenharmony_ci 358c2ecf20Sopenharmony_ci#define HMDFS_RETRY_WB_WQ_MAX_ACTIVE 16 368c2ecf20Sopenharmony_ci 378c2ecf20Sopenharmony_cistatic void hs_fill_crypto_data(struct connection *conn_impl, __u8 ops, 388c2ecf20Sopenharmony_ci void *data, __u32 len) 398c2ecf20Sopenharmony_ci{ 408c2ecf20Sopenharmony_ci struct crypto_body *body = NULL; 418c2ecf20Sopenharmony_ci 428c2ecf20Sopenharmony_ci if (len < sizeof(struct crypto_body)) { 438c2ecf20Sopenharmony_ci hmdfs_info("crpto body len %u is err", len); 448c2ecf20Sopenharmony_ci return; 458c2ecf20Sopenharmony_ci } 468c2ecf20Sopenharmony_ci body = (struct crypto_body *)data; 478c2ecf20Sopenharmony_ci 488c2ecf20Sopenharmony_ci /* this is only test, later need to fill right algorithm. */ 498c2ecf20Sopenharmony_ci body->crypto |= HMDFS_HS_CRYPTO_KTLS_AES128; 508c2ecf20Sopenharmony_ci body->crypto = cpu_to_le32(body->crypto); 518c2ecf20Sopenharmony_ci 528c2ecf20Sopenharmony_ci hmdfs_info("fill crypto. ccrtypto=0x%08x", body->crypto); 538c2ecf20Sopenharmony_ci} 548c2ecf20Sopenharmony_ci 558c2ecf20Sopenharmony_cistatic int hs_parse_crypto_data(struct connection *conn_impl, __u8 ops, 568c2ecf20Sopenharmony_ci void *data, __u32 len) 578c2ecf20Sopenharmony_ci{ 588c2ecf20Sopenharmony_ci struct crypto_body *hs_crypto = NULL; 598c2ecf20Sopenharmony_ci uint32_t crypto; 608c2ecf20Sopenharmony_ci 618c2ecf20Sopenharmony_ci if (len < sizeof(struct crypto_body)) { 628c2ecf20Sopenharmony_ci hmdfs_info("handshake msg len error, len=%u", len); 638c2ecf20Sopenharmony_ci return -1; 648c2ecf20Sopenharmony_ci } 658c2ecf20Sopenharmony_ci hs_crypto = (struct crypto_body *)data; 668c2ecf20Sopenharmony_ci crypto = le16_to_cpu(hs_crypto->crypto); 678c2ecf20Sopenharmony_ci conn_impl->crypto = crypto; 688c2ecf20Sopenharmony_ci hmdfs_info("ops=%u, len=%u, crypto=0x%08x", ops, len, crypto); 698c2ecf20Sopenharmony_ci return 0; 708c2ecf20Sopenharmony_ci} 718c2ecf20Sopenharmony_ci 728c2ecf20Sopenharmony_cistatic void hs_fill_case_sense_data(struct connection *conn_impl, __u8 ops, 738c2ecf20Sopenharmony_ci void *data, __u32 len) 748c2ecf20Sopenharmony_ci{ 758c2ecf20Sopenharmony_ci struct case_sense_body *body = (struct case_sense_body *)data; 768c2ecf20Sopenharmony_ci 778c2ecf20Sopenharmony_ci if (len < sizeof(struct case_sense_body)) { 788c2ecf20Sopenharmony_ci hmdfs_err("case sensitive len %u is err", len); 798c2ecf20Sopenharmony_ci return; 808c2ecf20Sopenharmony_ci } 818c2ecf20Sopenharmony_ci body->case_sensitive = conn_impl->node->sbi->s_case_sensitive; 828c2ecf20Sopenharmony_ci} 838c2ecf20Sopenharmony_ci 848c2ecf20Sopenharmony_cistatic int hs_parse_case_sense_data(struct connection *conn_impl, __u8 ops, 858c2ecf20Sopenharmony_ci void *data, __u32 len) 868c2ecf20Sopenharmony_ci{ 878c2ecf20Sopenharmony_ci struct case_sense_body *body = (struct case_sense_body *)data; 888c2ecf20Sopenharmony_ci __u8 sensitive = conn_impl->node->sbi->s_case_sensitive ? 1 : 0; 898c2ecf20Sopenharmony_ci 908c2ecf20Sopenharmony_ci if (len < sizeof(struct case_sense_body)) { 918c2ecf20Sopenharmony_ci hmdfs_info("case sensitive len %u is err", len); 928c2ecf20Sopenharmony_ci return -1; 938c2ecf20Sopenharmony_ci } 948c2ecf20Sopenharmony_ci if (body->case_sensitive != sensitive) { 958c2ecf20Sopenharmony_ci hmdfs_err("case sensitive inconsistent, server: %u,client: %u, ops: %u", 968c2ecf20Sopenharmony_ci body->case_sensitive, sensitive, ops); 978c2ecf20Sopenharmony_ci return -1; 988c2ecf20Sopenharmony_ci } 998c2ecf20Sopenharmony_ci return 0; 1008c2ecf20Sopenharmony_ci} 1018c2ecf20Sopenharmony_ci 1028c2ecf20Sopenharmony_cistatic void hs_fill_feature_data(struct connection *conn_impl, __u8 ops, 1038c2ecf20Sopenharmony_ci void *data, __u32 len) 1048c2ecf20Sopenharmony_ci{ 1058c2ecf20Sopenharmony_ci struct feature_body *body = (struct feature_body *)data; 1068c2ecf20Sopenharmony_ci 1078c2ecf20Sopenharmony_ci if (len < sizeof(struct feature_body)) { 1088c2ecf20Sopenharmony_ci hmdfs_err("feature len %u is err", len); 1098c2ecf20Sopenharmony_ci return; 1108c2ecf20Sopenharmony_ci } 1118c2ecf20Sopenharmony_ci body->features = cpu_to_le64(conn_impl->node->sbi->s_features); 1128c2ecf20Sopenharmony_ci body->reserved = cpu_to_le64(0); 1138c2ecf20Sopenharmony_ci} 1148c2ecf20Sopenharmony_ci 1158c2ecf20Sopenharmony_cistatic int hs_parse_feature_data(struct connection *conn_impl, __u8 ops, 1168c2ecf20Sopenharmony_ci void *data, __u32 len) 1178c2ecf20Sopenharmony_ci{ 1188c2ecf20Sopenharmony_ci struct feature_body *body = (struct feature_body *)data; 1198c2ecf20Sopenharmony_ci 1208c2ecf20Sopenharmony_ci if (len < sizeof(struct feature_body)) { 1218c2ecf20Sopenharmony_ci hmdfs_err("feature len %u is err", len); 1228c2ecf20Sopenharmony_ci return -1; 1238c2ecf20Sopenharmony_ci } 1248c2ecf20Sopenharmony_ci 1258c2ecf20Sopenharmony_ci conn_impl->node->features = le64_to_cpu(body->features); 1268c2ecf20Sopenharmony_ci return 0; 1278c2ecf20Sopenharmony_ci} 1288c2ecf20Sopenharmony_ci 1298c2ecf20Sopenharmony_ci/* should ensure len is small than 0xffff. */ 1308c2ecf20Sopenharmony_cistatic const struct conn_hs_extend_reg s_hs_extend_reg[HS_EXTEND_CODE_COUNT] = { 1318c2ecf20Sopenharmony_ci [HS_EXTEND_CODE_CRYPTO] = { 1328c2ecf20Sopenharmony_ci .len = sizeof(struct crypto_body), 1338c2ecf20Sopenharmony_ci .resv = 0, 1348c2ecf20Sopenharmony_ci .filler = hs_fill_crypto_data, 1358c2ecf20Sopenharmony_ci .parser = hs_parse_crypto_data 1368c2ecf20Sopenharmony_ci }, 1378c2ecf20Sopenharmony_ci [HS_EXTEND_CODE_CASE_SENSE] = { 1388c2ecf20Sopenharmony_ci .len = sizeof(struct case_sense_body), 1398c2ecf20Sopenharmony_ci .resv = 0, 1408c2ecf20Sopenharmony_ci .filler = hs_fill_case_sense_data, 1418c2ecf20Sopenharmony_ci .parser = hs_parse_case_sense_data, 1428c2ecf20Sopenharmony_ci }, 1438c2ecf20Sopenharmony_ci [HS_EXTEND_CODE_FEATURE_SUPPORT] = { 1448c2ecf20Sopenharmony_ci .len = sizeof(struct feature_body), 1458c2ecf20Sopenharmony_ci .resv = 0, 1468c2ecf20Sopenharmony_ci .filler = hs_fill_feature_data, 1478c2ecf20Sopenharmony_ci .parser = hs_parse_feature_data, 1488c2ecf20Sopenharmony_ci }, 1498c2ecf20Sopenharmony_ci [HS_EXTEND_CODE_FEATURE_SUPPORT] = { 1508c2ecf20Sopenharmony_ci .len = sizeof(struct feature_body), 1518c2ecf20Sopenharmony_ci .resv = 0, 1528c2ecf20Sopenharmony_ci .filler = hs_fill_feature_data, 1538c2ecf20Sopenharmony_ci .parser = hs_parse_feature_data, 1548c2ecf20Sopenharmony_ci }, 1558c2ecf20Sopenharmony_ci}; 1568c2ecf20Sopenharmony_ci 1578c2ecf20Sopenharmony_cistatic __u32 hs_get_extend_data_len(void) 1588c2ecf20Sopenharmony_ci{ 1598c2ecf20Sopenharmony_ci __u32 len; 1608c2ecf20Sopenharmony_ci int i; 1618c2ecf20Sopenharmony_ci 1628c2ecf20Sopenharmony_ci len = sizeof(struct conn_hs_extend_head); 1638c2ecf20Sopenharmony_ci 1648c2ecf20Sopenharmony_ci for (i = 0; i < HS_EXTEND_CODE_COUNT; i++) { 1658c2ecf20Sopenharmony_ci len += sizeof(struct extend_field_head); 1668c2ecf20Sopenharmony_ci len += s_hs_extend_reg[i].len; 1678c2ecf20Sopenharmony_ci } 1688c2ecf20Sopenharmony_ci 1698c2ecf20Sopenharmony_ci hmdfs_info("extend data total len is %u", len); 1708c2ecf20Sopenharmony_ci return len; 1718c2ecf20Sopenharmony_ci} 1728c2ecf20Sopenharmony_ci 1738c2ecf20Sopenharmony_cistatic void hs_fill_extend_data(struct connection *conn_impl, __u8 ops, 1748c2ecf20Sopenharmony_ci void *extend_data, __u32 len) 1758c2ecf20Sopenharmony_ci{ 1768c2ecf20Sopenharmony_ci struct conn_hs_extend_head *extend_head = NULL; 1778c2ecf20Sopenharmony_ci struct extend_field_head *field = NULL; 1788c2ecf20Sopenharmony_ci uint8_t *body = NULL; 1798c2ecf20Sopenharmony_ci __u32 offset; 1808c2ecf20Sopenharmony_ci __u16 i; 1818c2ecf20Sopenharmony_ci 1828c2ecf20Sopenharmony_ci if (sizeof(struct conn_hs_extend_head) > len) { 1838c2ecf20Sopenharmony_ci hmdfs_info("len error. len=%u", len); 1848c2ecf20Sopenharmony_ci return; 1858c2ecf20Sopenharmony_ci } 1868c2ecf20Sopenharmony_ci extend_head = (struct conn_hs_extend_head *)extend_data; 1878c2ecf20Sopenharmony_ci extend_head->field_cn = 0; 1888c2ecf20Sopenharmony_ci offset = sizeof(struct conn_hs_extend_head); 1898c2ecf20Sopenharmony_ci 1908c2ecf20Sopenharmony_ci for (i = 0; i < HS_EXTEND_CODE_COUNT; i++) { 1918c2ecf20Sopenharmony_ci if (sizeof(struct extend_field_head) > (len - offset)) 1928c2ecf20Sopenharmony_ci break; 1938c2ecf20Sopenharmony_ci field = (struct extend_field_head *)((uint8_t *)extend_data + 1948c2ecf20Sopenharmony_ci offset); 1958c2ecf20Sopenharmony_ci offset += sizeof(struct extend_field_head); 1968c2ecf20Sopenharmony_ci 1978c2ecf20Sopenharmony_ci if (s_hs_extend_reg[i].len > (len - offset)) 1988c2ecf20Sopenharmony_ci break; 1998c2ecf20Sopenharmony_ci body = (uint8_t *)extend_data + offset; 2008c2ecf20Sopenharmony_ci offset += s_hs_extend_reg[i].len; 2018c2ecf20Sopenharmony_ci 2028c2ecf20Sopenharmony_ci field->code = cpu_to_le16(i); 2038c2ecf20Sopenharmony_ci field->len = cpu_to_le16(s_hs_extend_reg[i].len); 2048c2ecf20Sopenharmony_ci 2058c2ecf20Sopenharmony_ci if (s_hs_extend_reg[i].filler) 2068c2ecf20Sopenharmony_ci s_hs_extend_reg[i].filler(conn_impl, ops, 2078c2ecf20Sopenharmony_ci body, s_hs_extend_reg[i].len); 2088c2ecf20Sopenharmony_ci 2098c2ecf20Sopenharmony_ci extend_head->field_cn += 1; 2108c2ecf20Sopenharmony_ci } 2118c2ecf20Sopenharmony_ci 2128c2ecf20Sopenharmony_ci extend_head->field_cn = cpu_to_le32(extend_head->field_cn); 2138c2ecf20Sopenharmony_ci} 2148c2ecf20Sopenharmony_ci 2158c2ecf20Sopenharmony_cistatic int hs_parse_extend_data(struct connection *conn_impl, __u8 ops, 2168c2ecf20Sopenharmony_ci void *extend_data, __u32 extend_len) 2178c2ecf20Sopenharmony_ci{ 2188c2ecf20Sopenharmony_ci struct conn_hs_extend_head *extend_head = NULL; 2198c2ecf20Sopenharmony_ci struct extend_field_head *field = NULL; 2208c2ecf20Sopenharmony_ci uint8_t *body = NULL; 2218c2ecf20Sopenharmony_ci __u32 offset; 2228c2ecf20Sopenharmony_ci __u32 field_cnt; 2238c2ecf20Sopenharmony_ci __u16 code; 2248c2ecf20Sopenharmony_ci __u16 len; 2258c2ecf20Sopenharmony_ci int i; 2268c2ecf20Sopenharmony_ci int ret; 2278c2ecf20Sopenharmony_ci 2288c2ecf20Sopenharmony_ci if (sizeof(struct conn_hs_extend_head) > extend_len) { 2298c2ecf20Sopenharmony_ci hmdfs_err("ops=%u,extend_len=%u", ops, extend_len); 2308c2ecf20Sopenharmony_ci return -1; 2318c2ecf20Sopenharmony_ci } 2328c2ecf20Sopenharmony_ci extend_head = (struct conn_hs_extend_head *)extend_data; 2338c2ecf20Sopenharmony_ci field_cnt = le32_to_cpu(extend_head->field_cn); 2348c2ecf20Sopenharmony_ci hmdfs_info("extend_len=%u,field_cnt=%u", extend_len, field_cnt); 2358c2ecf20Sopenharmony_ci 2368c2ecf20Sopenharmony_ci offset = sizeof(struct conn_hs_extend_head); 2378c2ecf20Sopenharmony_ci 2388c2ecf20Sopenharmony_ci for (i = 0; i < field_cnt; i++) { 2398c2ecf20Sopenharmony_ci if (sizeof(struct extend_field_head) > (extend_len - offset)) { 2408c2ecf20Sopenharmony_ci hmdfs_err("cnt err, op=%u, extend_len=%u, cnt=%u, i=%u", 2418c2ecf20Sopenharmony_ci ops, extend_len, field_cnt, i); 2428c2ecf20Sopenharmony_ci return -1; 2438c2ecf20Sopenharmony_ci } 2448c2ecf20Sopenharmony_ci field = (struct extend_field_head *)((uint8_t *)extend_data + 2458c2ecf20Sopenharmony_ci offset); 2468c2ecf20Sopenharmony_ci offset += sizeof(struct extend_field_head); 2478c2ecf20Sopenharmony_ci code = le16_to_cpu(field->code); 2488c2ecf20Sopenharmony_ci len = le16_to_cpu(field->len); 2498c2ecf20Sopenharmony_ci if (len > (extend_len - offset)) { 2508c2ecf20Sopenharmony_ci hmdfs_err("len err, op=%u, extend_len=%u, cnt=%u, i=%u", 2518c2ecf20Sopenharmony_ci ops, extend_len, field_cnt, i); 2528c2ecf20Sopenharmony_ci hmdfs_err("len err, code=%u, len=%u, offset=%u", code, 2538c2ecf20Sopenharmony_ci len, offset); 2548c2ecf20Sopenharmony_ci return -1; 2558c2ecf20Sopenharmony_ci } 2568c2ecf20Sopenharmony_ci 2578c2ecf20Sopenharmony_ci body = (uint8_t *)extend_data + offset; 2588c2ecf20Sopenharmony_ci offset += len; 2598c2ecf20Sopenharmony_ci if ((code < HS_EXTEND_CODE_COUNT) && 2608c2ecf20Sopenharmony_ci (s_hs_extend_reg[code].parser)) { 2618c2ecf20Sopenharmony_ci ret = s_hs_extend_reg[code].parser(conn_impl, ops, 2628c2ecf20Sopenharmony_ci body, len); 2638c2ecf20Sopenharmony_ci if (ret) 2648c2ecf20Sopenharmony_ci return ret; 2658c2ecf20Sopenharmony_ci } 2668c2ecf20Sopenharmony_ci } 2678c2ecf20Sopenharmony_ci return 0; 2688c2ecf20Sopenharmony_ci} 2698c2ecf20Sopenharmony_ci 2708c2ecf20Sopenharmony_cistatic int hs_proc_msg_data(struct connection *conn_impl, __u8 ops, void *data, 2718c2ecf20Sopenharmony_ci __u32 data_len) 2728c2ecf20Sopenharmony_ci{ 2738c2ecf20Sopenharmony_ci struct connection_handshake_req *hs_req = NULL; 2748c2ecf20Sopenharmony_ci uint8_t *extend_data = NULL; 2758c2ecf20Sopenharmony_ci __u32 extend_len; 2768c2ecf20Sopenharmony_ci __u32 req_len; 2778c2ecf20Sopenharmony_ci int ret; 2788c2ecf20Sopenharmony_ci 2798c2ecf20Sopenharmony_ci if (!data) { 2808c2ecf20Sopenharmony_ci hmdfs_err("err, msg data is null"); 2818c2ecf20Sopenharmony_ci return -1; 2828c2ecf20Sopenharmony_ci } 2838c2ecf20Sopenharmony_ci 2848c2ecf20Sopenharmony_ci if (data_len < sizeof(struct connection_handshake_req)) { 2858c2ecf20Sopenharmony_ci hmdfs_err("ack msg data len error. data_len=%u, device_id=%llu", 2868c2ecf20Sopenharmony_ci data_len, conn_impl->node->device_id); 2878c2ecf20Sopenharmony_ci return -1; 2888c2ecf20Sopenharmony_ci } 2898c2ecf20Sopenharmony_ci 2908c2ecf20Sopenharmony_ci hs_req = (struct connection_handshake_req *)data; 2918c2ecf20Sopenharmony_ci req_len = le32_to_cpu(hs_req->len); 2928c2ecf20Sopenharmony_ci if (req_len > (data_len - sizeof(struct connection_handshake_req))) { 2938c2ecf20Sopenharmony_ci hmdfs_info( 2948c2ecf20Sopenharmony_ci "ack msg hs_req len(%u) error. data_len=%u, device_id=%llu", 2958c2ecf20Sopenharmony_ci req_len, data_len, conn_impl->node->device_id); 2968c2ecf20Sopenharmony_ci return -1; 2978c2ecf20Sopenharmony_ci } 2988c2ecf20Sopenharmony_ci extend_len = 2998c2ecf20Sopenharmony_ci data_len - sizeof(struct connection_handshake_req) - req_len; 3008c2ecf20Sopenharmony_ci extend_data = (uint8_t *)data + 3018c2ecf20Sopenharmony_ci sizeof(struct connection_handshake_req) + req_len; 3028c2ecf20Sopenharmony_ci ret = hs_parse_extend_data(conn_impl, ops, extend_data, extend_len); 3038c2ecf20Sopenharmony_ci if (!ret) 3048c2ecf20Sopenharmony_ci hmdfs_info( 3058c2ecf20Sopenharmony_ci "hs msg rcv, ops=%u, data_len=%u, device_id=%llu, req_len=%u", 3068c2ecf20Sopenharmony_ci ops, data_len, conn_impl->node->device_id, hs_req->len); 3078c2ecf20Sopenharmony_ci return ret; 3088c2ecf20Sopenharmony_ci} 3098c2ecf20Sopenharmony_ci#ifdef CONFIG_HMDFS_FS_ENCRYPTION 3108c2ecf20Sopenharmony_cistatic int connection_handshake_init_tls(struct connection *conn_impl, __u8 ops) 3118c2ecf20Sopenharmony_ci{ 3128c2ecf20Sopenharmony_ci // init ktls config, use key1/key2 as init write-key of each direction 3138c2ecf20Sopenharmony_ci __u8 key1[HMDFS_KEY_SIZE]; 3148c2ecf20Sopenharmony_ci __u8 key2[HMDFS_KEY_SIZE]; 3158c2ecf20Sopenharmony_ci int ret; 3168c2ecf20Sopenharmony_ci 3178c2ecf20Sopenharmony_ci if ((ops != CONNECT_MESG_HANDSHAKE_RESPONSE) && 3188c2ecf20Sopenharmony_ci (ops != CONNECT_MESG_HANDSHAKE_ACK)) { 3198c2ecf20Sopenharmony_ci hmdfs_err("ops %u is err", ops); 3208c2ecf20Sopenharmony_ci return -EINVAL; 3218c2ecf20Sopenharmony_ci } 3228c2ecf20Sopenharmony_ci 3238c2ecf20Sopenharmony_ci update_key(conn_impl->master_key, key1, HKDF_TYPE_KEY_INITIATOR); 3248c2ecf20Sopenharmony_ci update_key(conn_impl->master_key, key2, HKDF_TYPE_KEY_ACCEPTER); 3258c2ecf20Sopenharmony_ci 3268c2ecf20Sopenharmony_ci if (ops == CONNECT_MESG_HANDSHAKE_ACK) { 3278c2ecf20Sopenharmony_ci memcpy(conn_impl->send_key, key1, HMDFS_KEY_SIZE); 3288c2ecf20Sopenharmony_ci memcpy(conn_impl->recv_key, key2, HMDFS_KEY_SIZE); 3298c2ecf20Sopenharmony_ci } else { 3308c2ecf20Sopenharmony_ci memcpy(conn_impl->send_key, key2, HMDFS_KEY_SIZE); 3318c2ecf20Sopenharmony_ci memcpy(conn_impl->recv_key, key1, HMDFS_KEY_SIZE); 3328c2ecf20Sopenharmony_ci } 3338c2ecf20Sopenharmony_ci 3348c2ecf20Sopenharmony_ci memset(key1, 0, HMDFS_KEY_SIZE); 3358c2ecf20Sopenharmony_ci memset(key2, 0, HMDFS_KEY_SIZE); 3368c2ecf20Sopenharmony_ci 3378c2ecf20Sopenharmony_ci hmdfs_info("hs: ops=%u start set crypto tls", ops); 3388c2ecf20Sopenharmony_ci ret = tls_crypto_info_init(conn_impl); 3398c2ecf20Sopenharmony_ci if (ret) 3408c2ecf20Sopenharmony_ci hmdfs_err("setting tls fail. ops is %u", ops); 3418c2ecf20Sopenharmony_ci 3428c2ecf20Sopenharmony_ci return ret; 3438c2ecf20Sopenharmony_ci} 3448c2ecf20Sopenharmony_ci#endif 3458c2ecf20Sopenharmony_ci 3468c2ecf20Sopenharmony_cistatic int do_send_handshake(struct connection *conn_impl, __u8 ops, 3478c2ecf20Sopenharmony_ci __le16 request_id) 3488c2ecf20Sopenharmony_ci{ 3498c2ecf20Sopenharmony_ci int err; 3508c2ecf20Sopenharmony_ci struct connection_msg_head *hs_head = NULL; 3518c2ecf20Sopenharmony_ci struct connection_handshake_req *hs_data = NULL; 3528c2ecf20Sopenharmony_ci uint8_t *hs_extend_data = NULL; 3538c2ecf20Sopenharmony_ci struct hmdfs_send_data msg; 3548c2ecf20Sopenharmony_ci __u32 send_len; 3558c2ecf20Sopenharmony_ci __u32 len; 3568c2ecf20Sopenharmony_ci __u32 extend_len; 3578c2ecf20Sopenharmony_ci char buf[HMDFS_CID_SIZE] = { 0 }; 3588c2ecf20Sopenharmony_ci 3598c2ecf20Sopenharmony_ci len = scnprintf(buf, HMDFS_CID_SIZE, "%llu", 0ULL); 3608c2ecf20Sopenharmony_ci send_len = sizeof(struct connection_msg_head) + 3618c2ecf20Sopenharmony_ci sizeof(struct connection_handshake_req) + len; 3628c2ecf20Sopenharmony_ci 3638c2ecf20Sopenharmony_ci if (((ops == CONNECT_MESG_HANDSHAKE_RESPONSE) || 3648c2ecf20Sopenharmony_ci (ops == CONNECT_MESG_HANDSHAKE_ACK))) { 3658c2ecf20Sopenharmony_ci extend_len = hs_get_extend_data_len(); 3668c2ecf20Sopenharmony_ci send_len += extend_len; 3678c2ecf20Sopenharmony_ci } 3688c2ecf20Sopenharmony_ci 3698c2ecf20Sopenharmony_ci hs_head = kzalloc(send_len, GFP_KERNEL); 3708c2ecf20Sopenharmony_ci if (!hs_head) 3718c2ecf20Sopenharmony_ci return -ENOMEM; 3728c2ecf20Sopenharmony_ci 3738c2ecf20Sopenharmony_ci hs_data = (struct connection_handshake_req 3748c2ecf20Sopenharmony_ci *)((uint8_t *)hs_head + 3758c2ecf20Sopenharmony_ci sizeof(struct connection_msg_head)); 3768c2ecf20Sopenharmony_ci 3778c2ecf20Sopenharmony_ci hs_data->len = cpu_to_le32(len); 3788c2ecf20Sopenharmony_ci memcpy(hs_data->dev_id, buf, len); 3798c2ecf20Sopenharmony_ci 3808c2ecf20Sopenharmony_ci if (((ops == CONNECT_MESG_HANDSHAKE_RESPONSE) || 3818c2ecf20Sopenharmony_ci ops == CONNECT_MESG_HANDSHAKE_ACK)) { 3828c2ecf20Sopenharmony_ci hs_extend_data = (uint8_t *)hs_data + 3838c2ecf20Sopenharmony_ci sizeof(struct connection_handshake_req) + len; 3848c2ecf20Sopenharmony_ci hs_fill_extend_data(conn_impl, ops, hs_extend_data, extend_len); 3858c2ecf20Sopenharmony_ci } 3868c2ecf20Sopenharmony_ci 3878c2ecf20Sopenharmony_ci hs_head->magic = HMDFS_MSG_MAGIC; 3888c2ecf20Sopenharmony_ci hs_head->version = HMDFS_VERSION; 3898c2ecf20Sopenharmony_ci hs_head->flags |= 0x1; 3908c2ecf20Sopenharmony_ci hmdfs_info("Send handshake message: ops = %d, fd = %d", ops, 3918c2ecf20Sopenharmony_ci ((struct tcp_handle *)(conn_impl->connect_handle))->fd); 3928c2ecf20Sopenharmony_ci hs_head->operations = ops; 3938c2ecf20Sopenharmony_ci hs_head->request_id = request_id; 3948c2ecf20Sopenharmony_ci hs_head->datasize = cpu_to_le32(send_len); 3958c2ecf20Sopenharmony_ci hs_head->source = 0; 3968c2ecf20Sopenharmony_ci hs_head->msg_id = 0; 3978c2ecf20Sopenharmony_ci 3988c2ecf20Sopenharmony_ci msg.head = hs_head; 3998c2ecf20Sopenharmony_ci msg.head_len = sizeof(struct connection_msg_head); 4008c2ecf20Sopenharmony_ci msg.data = hs_data; 4018c2ecf20Sopenharmony_ci msg.len = send_len - msg.head_len; 4028c2ecf20Sopenharmony_ci msg.sdesc = NULL; 4038c2ecf20Sopenharmony_ci msg.sdesc_len = 0; 4048c2ecf20Sopenharmony_ci err = conn_impl->send_message(conn_impl, &msg); 4058c2ecf20Sopenharmony_ci kfree(hs_head); 4068c2ecf20Sopenharmony_ci return err; 4078c2ecf20Sopenharmony_ci} 4088c2ecf20Sopenharmony_ci 4098c2ecf20Sopenharmony_cistatic int hmdfs_node_waiting_evt_sum(const struct hmdfs_peer *node) 4108c2ecf20Sopenharmony_ci{ 4118c2ecf20Sopenharmony_ci int sum = 0; 4128c2ecf20Sopenharmony_ci int i; 4138c2ecf20Sopenharmony_ci 4148c2ecf20Sopenharmony_ci for (i = 0; i < RAW_NODE_EVT_NR; i++) 4158c2ecf20Sopenharmony_ci sum += node->waiting_evt[i]; 4168c2ecf20Sopenharmony_ci 4178c2ecf20Sopenharmony_ci return sum; 4188c2ecf20Sopenharmony_ci} 4198c2ecf20Sopenharmony_ci 4208c2ecf20Sopenharmony_cistatic int hmdfs_update_node_waiting_evt(struct hmdfs_peer *node, int evt, 4218c2ecf20Sopenharmony_ci unsigned int *seq) 4228c2ecf20Sopenharmony_ci{ 4238c2ecf20Sopenharmony_ci int last; 4248c2ecf20Sopenharmony_ci int sum; 4258c2ecf20Sopenharmony_ci unsigned int next; 4268c2ecf20Sopenharmony_ci 4278c2ecf20Sopenharmony_ci sum = hmdfs_node_waiting_evt_sum(node); 4288c2ecf20Sopenharmony_ci if (sum % RAW_NODE_EVT_NR) 4298c2ecf20Sopenharmony_ci last = !node->pending_evt; 4308c2ecf20Sopenharmony_ci else 4318c2ecf20Sopenharmony_ci last = node->pending_evt; 4328c2ecf20Sopenharmony_ci 4338c2ecf20Sopenharmony_ci /* duplicated event */ 4348c2ecf20Sopenharmony_ci if (evt == last) { 4358c2ecf20Sopenharmony_ci node->dup_evt[evt]++; 4368c2ecf20Sopenharmony_ci return 0; 4378c2ecf20Sopenharmony_ci } 4388c2ecf20Sopenharmony_ci 4398c2ecf20Sopenharmony_ci node->waiting_evt[evt]++; 4408c2ecf20Sopenharmony_ci hmdfs_debug("add node->waiting_evt[%d]=%d", evt, 4418c2ecf20Sopenharmony_ci node->waiting_evt[evt]); 4428c2ecf20Sopenharmony_ci 4438c2ecf20Sopenharmony_ci /* offline wait + online wait + offline wait = offline wait 4448c2ecf20Sopenharmony_ci * online wait + offline wait + online wait != online wait 4458c2ecf20Sopenharmony_ci * As the first online related resource (e.g. fd) must be invalidated 4468c2ecf20Sopenharmony_ci */ 4478c2ecf20Sopenharmony_ci if (node->waiting_evt[RAW_NODE_EVT_OFF] >= 2 && 4488c2ecf20Sopenharmony_ci node->waiting_evt[RAW_NODE_EVT_ON] >= 1) { 4498c2ecf20Sopenharmony_ci node->waiting_evt[RAW_NODE_EVT_OFF] -= 1; 4508c2ecf20Sopenharmony_ci node->waiting_evt[RAW_NODE_EVT_ON] -= 1; 4518c2ecf20Sopenharmony_ci node->seq_wr_idx -= 2; 4528c2ecf20Sopenharmony_ci node->merged_evt += 2; 4538c2ecf20Sopenharmony_ci } 4548c2ecf20Sopenharmony_ci 4558c2ecf20Sopenharmony_ci next = hmdfs_node_inc_evt_seq(node); 4568c2ecf20Sopenharmony_ci node->seq_tbl[(node->seq_wr_idx++) % RAW_NODE_EVT_MAX_NR] = next; 4578c2ecf20Sopenharmony_ci *seq = next; 4588c2ecf20Sopenharmony_ci 4598c2ecf20Sopenharmony_ci return 1; 4608c2ecf20Sopenharmony_ci} 4618c2ecf20Sopenharmony_ci 4628c2ecf20Sopenharmony_cistatic void hmdfs_run_evt_cb_verbosely(struct hmdfs_peer *node, int raw_evt, 4638c2ecf20Sopenharmony_ci bool sync, unsigned int seq) 4648c2ecf20Sopenharmony_ci{ 4658c2ecf20Sopenharmony_ci int evt = (raw_evt == RAW_NODE_EVT_OFF) ? NODE_EVT_OFFLINE : 4668c2ecf20Sopenharmony_ci NODE_EVT_ONLINE; 4678c2ecf20Sopenharmony_ci int cur_evt_idx = sync ? 1 : 0; 4688c2ecf20Sopenharmony_ci 4698c2ecf20Sopenharmony_ci node->cur_evt[cur_evt_idx] = raw_evt; 4708c2ecf20Sopenharmony_ci node->cur_evt_seq[cur_evt_idx] = seq; 4718c2ecf20Sopenharmony_ci hmdfs_node_call_evt_cb(node, evt, sync, seq); 4728c2ecf20Sopenharmony_ci node->cur_evt[cur_evt_idx] = RAW_NODE_EVT_NR; 4738c2ecf20Sopenharmony_ci} 4748c2ecf20Sopenharmony_ci 4758c2ecf20Sopenharmony_cistatic void hmdfs_node_evt_work(struct work_struct *work) 4768c2ecf20Sopenharmony_ci{ 4778c2ecf20Sopenharmony_ci struct hmdfs_peer *node = 4788c2ecf20Sopenharmony_ci container_of(work, struct hmdfs_peer, evt_dwork.work); 4798c2ecf20Sopenharmony_ci unsigned int seq; 4808c2ecf20Sopenharmony_ci 4818c2ecf20Sopenharmony_ci /* 4828c2ecf20Sopenharmony_ci * N-th sync cb completes before N-th async cb, 4838c2ecf20Sopenharmony_ci * so use seq_lock as a barrier in read & write path 4848c2ecf20Sopenharmony_ci * to ensure we can read the required seq. 4858c2ecf20Sopenharmony_ci */ 4868c2ecf20Sopenharmony_ci mutex_lock(&node->seq_lock); 4878c2ecf20Sopenharmony_ci seq = node->seq_tbl[(node->seq_rd_idx++) % RAW_NODE_EVT_MAX_NR]; 4888c2ecf20Sopenharmony_ci hmdfs_run_evt_cb_verbosely(node, node->pending_evt, false, seq); 4898c2ecf20Sopenharmony_ci mutex_unlock(&node->seq_lock); 4908c2ecf20Sopenharmony_ci 4918c2ecf20Sopenharmony_ci mutex_lock(&node->evt_lock); 4928c2ecf20Sopenharmony_ci if (hmdfs_node_waiting_evt_sum(node)) { 4938c2ecf20Sopenharmony_ci node->pending_evt = !node->pending_evt; 4948c2ecf20Sopenharmony_ci node->pending_evt_seq = 4958c2ecf20Sopenharmony_ci node->seq_tbl[node->seq_rd_idx % RAW_NODE_EVT_MAX_NR]; 4968c2ecf20Sopenharmony_ci node->waiting_evt[node->pending_evt]--; 4978c2ecf20Sopenharmony_ci /* sync cb has been done */ 4988c2ecf20Sopenharmony_ci schedule_delayed_work(&node->evt_dwork, 4998c2ecf20Sopenharmony_ci node->sbi->async_cb_delay * HZ); 5008c2ecf20Sopenharmony_ci } else { 5018c2ecf20Sopenharmony_ci node->last_evt = node->pending_evt; 5028c2ecf20Sopenharmony_ci node->pending_evt = RAW_NODE_EVT_NR; 5038c2ecf20Sopenharmony_ci } 5048c2ecf20Sopenharmony_ci mutex_unlock(&node->evt_lock); 5058c2ecf20Sopenharmony_ci} 5068c2ecf20Sopenharmony_ci 5078c2ecf20Sopenharmony_ci/* 5088c2ecf20Sopenharmony_ci * The running orders of cb are: 5098c2ecf20Sopenharmony_ci * 5108c2ecf20Sopenharmony_ci * (1) sync callbacks are invoked according to the queue order of raw events: 5118c2ecf20Sopenharmony_ci * ensured by seq_lock. 5128c2ecf20Sopenharmony_ci * (2) async callbacks are invoked according to the queue order of raw events: 5138c2ecf20Sopenharmony_ci * ensured by evt_lock & evt_dwork 5148c2ecf20Sopenharmony_ci * (3) async callback is invoked after sync callback of the same raw event: 5158c2ecf20Sopenharmony_ci * ensured by seq_lock. 5168c2ecf20Sopenharmony_ci * (4) async callback of N-th raw event and sync callback of (N+x)-th raw 5178c2ecf20Sopenharmony_ci * event can run concurrently. 5188c2ecf20Sopenharmony_ci */ 5198c2ecf20Sopenharmony_cistatic void hmdfs_queue_raw_node_evt(struct hmdfs_peer *node, int evt) 5208c2ecf20Sopenharmony_ci{ 5218c2ecf20Sopenharmony_ci unsigned int seq = 0; 5228c2ecf20Sopenharmony_ci 5238c2ecf20Sopenharmony_ci mutex_lock(&node->evt_lock); 5248c2ecf20Sopenharmony_ci if (node->pending_evt == RAW_NODE_EVT_NR) { 5258c2ecf20Sopenharmony_ci if (evt == node->last_evt) { 5268c2ecf20Sopenharmony_ci node->dup_evt[evt]++; 5278c2ecf20Sopenharmony_ci mutex_unlock(&node->evt_lock); 5288c2ecf20Sopenharmony_ci return; 5298c2ecf20Sopenharmony_ci } 5308c2ecf20Sopenharmony_ci node->pending_evt = evt; 5318c2ecf20Sopenharmony_ci seq = hmdfs_node_inc_evt_seq(node); 5328c2ecf20Sopenharmony_ci node->seq_tbl[(node->seq_wr_idx++) % RAW_NODE_EVT_MAX_NR] = seq; 5338c2ecf20Sopenharmony_ci node->pending_evt_seq = seq; 5348c2ecf20Sopenharmony_ci mutex_lock(&node->seq_lock); 5358c2ecf20Sopenharmony_ci mutex_unlock(&node->evt_lock); 5368c2ecf20Sopenharmony_ci /* call sync cb, then async cb */ 5378c2ecf20Sopenharmony_ci hmdfs_run_evt_cb_verbosely(node, evt, true, seq); 5388c2ecf20Sopenharmony_ci mutex_unlock(&node->seq_lock); 5398c2ecf20Sopenharmony_ci schedule_delayed_work(&node->evt_dwork, 5408c2ecf20Sopenharmony_ci node->sbi->async_cb_delay * HZ); 5418c2ecf20Sopenharmony_ci } else if (hmdfs_update_node_waiting_evt(node, evt, &seq) > 0) { 5428c2ecf20Sopenharmony_ci /* 5438c2ecf20Sopenharmony_ci * Take seq_lock firstly to ensure N-th sync cb 5448c2ecf20Sopenharmony_ci * is called before N-th async cb. 5458c2ecf20Sopenharmony_ci */ 5468c2ecf20Sopenharmony_ci mutex_lock(&node->seq_lock); 5478c2ecf20Sopenharmony_ci mutex_unlock(&node->evt_lock); 5488c2ecf20Sopenharmony_ci hmdfs_run_evt_cb_verbosely(node, evt, true, seq); 5498c2ecf20Sopenharmony_ci mutex_unlock(&node->seq_lock); 5508c2ecf20Sopenharmony_ci } else { 5518c2ecf20Sopenharmony_ci mutex_unlock(&node->evt_lock); 5528c2ecf20Sopenharmony_ci } 5538c2ecf20Sopenharmony_ci} 5548c2ecf20Sopenharmony_ci 5558c2ecf20Sopenharmony_civoid connection_send_handshake(struct connection *conn_impl, __u8 ops, 5568c2ecf20Sopenharmony_ci __le16 request_id) 5578c2ecf20Sopenharmony_ci{ 5588c2ecf20Sopenharmony_ci struct tcp_handle *tcp = NULL; 5598c2ecf20Sopenharmony_ci int err = do_send_handshake(conn_impl, ops, request_id); 5608c2ecf20Sopenharmony_ci 5618c2ecf20Sopenharmony_ci if (likely(err >= 0)) 5628c2ecf20Sopenharmony_ci return; 5638c2ecf20Sopenharmony_ci 5648c2ecf20Sopenharmony_ci tcp = conn_impl->connect_handle; 5658c2ecf20Sopenharmony_ci hmdfs_err("Failed to send handshake: err = %d, fd = %d", err, tcp->fd); 5668c2ecf20Sopenharmony_ci hmdfs_reget_connection(conn_impl); 5678c2ecf20Sopenharmony_ci} 5688c2ecf20Sopenharmony_ci 5698c2ecf20Sopenharmony_civoid connection_handshake_notify(struct hmdfs_peer *node, int notify_type) 5708c2ecf20Sopenharmony_ci{ 5718c2ecf20Sopenharmony_ci struct notify_param param; 5728c2ecf20Sopenharmony_ci 5738c2ecf20Sopenharmony_ci param.notify = notify_type; 5748c2ecf20Sopenharmony_ci param.fd = INVALID_SOCKET_FD; 5758c2ecf20Sopenharmony_ci memcpy(param.remote_cid, node->cid, HMDFS_CID_SIZE); 5768c2ecf20Sopenharmony_ci notify(node, ¶m); 5778c2ecf20Sopenharmony_ci} 5788c2ecf20Sopenharmony_ci 5798c2ecf20Sopenharmony_ci 5808c2ecf20Sopenharmony_civoid peer_online(struct hmdfs_peer *peer) 5818c2ecf20Sopenharmony_ci{ 5828c2ecf20Sopenharmony_ci // To evaluate if someone else has made the peer online 5838c2ecf20Sopenharmony_ci u8 prev_stat = xchg(&peer->status, NODE_STAT_ONLINE); 5848c2ecf20Sopenharmony_ci unsigned long jif_tmp = jiffies; 5858c2ecf20Sopenharmony_ci 5868c2ecf20Sopenharmony_ci if (prev_stat == NODE_STAT_ONLINE) 5878c2ecf20Sopenharmony_ci return; 5888c2ecf20Sopenharmony_ci WRITE_ONCE(peer->conn_time, jif_tmp); 5898c2ecf20Sopenharmony_ci WRITE_ONCE(peer->sbi->connections.recent_ol, jif_tmp); 5908c2ecf20Sopenharmony_ci hmdfs_queue_raw_node_evt(peer, RAW_NODE_EVT_ON); 5918c2ecf20Sopenharmony_ci} 5928c2ecf20Sopenharmony_ci 5938c2ecf20Sopenharmony_civoid connection_to_working(struct hmdfs_peer *node) 5948c2ecf20Sopenharmony_ci{ 5958c2ecf20Sopenharmony_ci struct connection *conn_impl = NULL; 5968c2ecf20Sopenharmony_ci struct tcp_handle *tcp = NULL; 5978c2ecf20Sopenharmony_ci 5988c2ecf20Sopenharmony_ci if (!node) 5998c2ecf20Sopenharmony_ci return; 6008c2ecf20Sopenharmony_ci mutex_lock(&node->conn_impl_list_lock); 6018c2ecf20Sopenharmony_ci list_for_each_entry(conn_impl, &node->conn_impl_list, list) { 6028c2ecf20Sopenharmony_ci if (conn_impl->type == CONNECT_TYPE_TCP && 6038c2ecf20Sopenharmony_ci conn_impl->status == CONNECT_STAT_WAIT_RESPONSE) { 6048c2ecf20Sopenharmony_ci tcp = conn_impl->connect_handle; 6058c2ecf20Sopenharmony_ci hmdfs_info("fd %d to working", tcp->fd); 6068c2ecf20Sopenharmony_ci conn_impl->status = CONNECT_STAT_WORKING; 6078c2ecf20Sopenharmony_ci } 6088c2ecf20Sopenharmony_ci } 6098c2ecf20Sopenharmony_ci mutex_unlock(&node->conn_impl_list_lock); 6108c2ecf20Sopenharmony_ci peer_online(node); 6118c2ecf20Sopenharmony_ci} 6128c2ecf20Sopenharmony_ci 6138c2ecf20Sopenharmony_civoid connection_handshake_recv_handler(struct connection *conn_impl, void *buf, 6148c2ecf20Sopenharmony_ci void *data, __u32 data_len) 6158c2ecf20Sopenharmony_ci{ 6168c2ecf20Sopenharmony_ci __u8 ops; 6178c2ecf20Sopenharmony_ci __u8 status; 6188c2ecf20Sopenharmony_ci int fd = ((struct tcp_handle *)(conn_impl->connect_handle))->fd; 6198c2ecf20Sopenharmony_ci struct connection_msg_head *head = (struct connection_msg_head *)buf; 6208c2ecf20Sopenharmony_ci int ret; 6218c2ecf20Sopenharmony_ci 6228c2ecf20Sopenharmony_ci if (head->version != HMDFS_VERSION) 6238c2ecf20Sopenharmony_ci goto out; 6248c2ecf20Sopenharmony_ci 6258c2ecf20Sopenharmony_ci conn_impl->node->version = head->version; 6268c2ecf20Sopenharmony_ci ops = head->operations; 6278c2ecf20Sopenharmony_ci status = conn_impl->status; 6288c2ecf20Sopenharmony_ci switch (ops) { 6298c2ecf20Sopenharmony_ci case CONNECT_MESG_HANDSHAKE_REQUEST: 6308c2ecf20Sopenharmony_ci hmdfs_info( 6318c2ecf20Sopenharmony_ci "Recved handshake request: device_id = %llu, head->len = %d, tcp->fd = %d", 6328c2ecf20Sopenharmony_ci conn_impl->node->device_id, head->datasize, fd); 6338c2ecf20Sopenharmony_ci connection_send_handshake(conn_impl, 6348c2ecf20Sopenharmony_ci CONNECT_MESG_HANDSHAKE_RESPONSE, 6358c2ecf20Sopenharmony_ci head->msg_id); 6368c2ecf20Sopenharmony_ci conn_impl->status = CONNECT_STAT_WAIT_ACK; 6378c2ecf20Sopenharmony_ci conn_impl->node->status = NODE_STAT_SHAKING; 6388c2ecf20Sopenharmony_ci break; 6398c2ecf20Sopenharmony_ci case CONNECT_MESG_HANDSHAKE_RESPONSE: 6408c2ecf20Sopenharmony_ci hmdfs_info( 6418c2ecf20Sopenharmony_ci "Recved handshake response: device_id = %llu, cmd->status = %hhu, tcp->fd = %d", 6428c2ecf20Sopenharmony_ci conn_impl->node->device_id, status, fd); 6438c2ecf20Sopenharmony_ci 6448c2ecf20Sopenharmony_ci ret = hs_proc_msg_data(conn_impl, ops, data, data_len); 6458c2ecf20Sopenharmony_ci if (ret) 6468c2ecf20Sopenharmony_ci goto nego_err; 6478c2ecf20Sopenharmony_ci connection_send_handshake(conn_impl, 6488c2ecf20Sopenharmony_ci CONNECT_MESG_HANDSHAKE_ACK, 6498c2ecf20Sopenharmony_ci head->msg_id); 6508c2ecf20Sopenharmony_ci hmdfs_info("respon rcv handle,conn_impl->crypto=0x%0x", 6518c2ecf20Sopenharmony_ci conn_impl->crypto); 6528c2ecf20Sopenharmony_ci#ifdef CONFIG_HMDFS_FS_ENCRYPTION 6538c2ecf20Sopenharmony_ci ret = connection_handshake_init_tls(conn_impl, ops); 6548c2ecf20Sopenharmony_ci if (ret) { 6558c2ecf20Sopenharmony_ci hmdfs_err("init_tls_key fail, ops %u", ops); 6568c2ecf20Sopenharmony_ci goto out; 6578c2ecf20Sopenharmony_ci } 6588c2ecf20Sopenharmony_ci#endif 6598c2ecf20Sopenharmony_ci 6608c2ecf20Sopenharmony_ci conn_impl->status = CONNECT_STAT_WORKING; 6618c2ecf20Sopenharmony_ci peer_online(conn_impl->node); 6628c2ecf20Sopenharmony_ci break; 6638c2ecf20Sopenharmony_ci case CONNECT_MESG_HANDSHAKE_ACK: 6648c2ecf20Sopenharmony_ci ret = hs_proc_msg_data(conn_impl, ops, data, data_len); 6658c2ecf20Sopenharmony_ci if (ret) 6668c2ecf20Sopenharmony_ci goto nego_err; 6678c2ecf20Sopenharmony_ci hmdfs_info("ack rcv handle, conn_impl->crypto=0x%0x", 6688c2ecf20Sopenharmony_ci conn_impl->crypto); 6698c2ecf20Sopenharmony_ci#ifdef CONFIG_HMDFS_FS_ENCRYPTION 6708c2ecf20Sopenharmony_ci ret = connection_handshake_init_tls(conn_impl, ops); 6718c2ecf20Sopenharmony_ci if (ret) { 6728c2ecf20Sopenharmony_ci hmdfs_err("init_tls_key fail, ops %u", ops); 6738c2ecf20Sopenharmony_ci goto out; 6748c2ecf20Sopenharmony_ci } 6758c2ecf20Sopenharmony_ci#endif 6768c2ecf20Sopenharmony_ci conn_impl->status = CONNECT_STAT_WORKING; 6778c2ecf20Sopenharmony_ci peer_online(conn_impl->node); 6788c2ecf20Sopenharmony_ci break; 6798c2ecf20Sopenharmony_ci fallthrough; 6808c2ecf20Sopenharmony_ci default: 6818c2ecf20Sopenharmony_ci break; 6828c2ecf20Sopenharmony_ci } 6838c2ecf20Sopenharmony_ciout: 6848c2ecf20Sopenharmony_ci kfree(data); 6858c2ecf20Sopenharmony_ci return; 6868c2ecf20Sopenharmony_cinego_err: 6878c2ecf20Sopenharmony_ci conn_impl->status = CONNECT_STAT_NEGO_FAIL; 6888c2ecf20Sopenharmony_ci connection_handshake_notify(conn_impl->node, NOTIFY_OFFLINE); 6898c2ecf20Sopenharmony_ci hmdfs_err("protocol negotiation failed, remote device_id = %llu, tcp->fd = %d", 6908c2ecf20Sopenharmony_ci conn_impl->node->device_id, fd); 6918c2ecf20Sopenharmony_ci goto out; 6928c2ecf20Sopenharmony_ci} 6938c2ecf20Sopenharmony_ci 6948c2ecf20Sopenharmony_ci#ifdef CONFIG_HMDFS_FS_ENCRYPTION 6958c2ecf20Sopenharmony_cistatic void update_tls_crypto_key(struct connection *conn, 6968c2ecf20Sopenharmony_ci struct hmdfs_head_cmd *head, void *data, 6978c2ecf20Sopenharmony_ci __u32 data_len) 6988c2ecf20Sopenharmony_ci{ 6998c2ecf20Sopenharmony_ci // rekey message handler 7008c2ecf20Sopenharmony_ci struct connection_rekey_request *rekey_req = NULL; 7018c2ecf20Sopenharmony_ci int ret = 0; 7028c2ecf20Sopenharmony_ci 7038c2ecf20Sopenharmony_ci if (hmdfs_message_verify(conn->node, head, data) < 0) { 7048c2ecf20Sopenharmony_ci hmdfs_err("Rekey msg %d has been abandoned", head->msg_id); 7058c2ecf20Sopenharmony_ci goto out_err; 7068c2ecf20Sopenharmony_ci } 7078c2ecf20Sopenharmony_ci 7088c2ecf20Sopenharmony_ci hmdfs_info("recv REKEY request"); 7098c2ecf20Sopenharmony_ci set_crypto_info(conn, SET_CRYPTO_RECV); 7108c2ecf20Sopenharmony_ci // update send key if requested 7118c2ecf20Sopenharmony_ci rekey_req = data; 7128c2ecf20Sopenharmony_ci if (le32_to_cpu(rekey_req->update_request) == UPDATE_REQUESTED) { 7138c2ecf20Sopenharmony_ci ret = tcp_send_rekey_request(conn); 7148c2ecf20Sopenharmony_ci if (ret == 0) 7158c2ecf20Sopenharmony_ci set_crypto_info(conn, SET_CRYPTO_SEND); 7168c2ecf20Sopenharmony_ci } 7178c2ecf20Sopenharmony_ciout_err: 7188c2ecf20Sopenharmony_ci kfree(data); 7198c2ecf20Sopenharmony_ci} 7208c2ecf20Sopenharmony_ci 7218c2ecf20Sopenharmony_cistatic bool cmd_update_tls_crypto_key(struct connection *conn, 7228c2ecf20Sopenharmony_ci struct hmdfs_head_cmd *head) 7238c2ecf20Sopenharmony_ci{ 7248c2ecf20Sopenharmony_ci struct tcp_handle *tcp = conn->connect_handle; 7258c2ecf20Sopenharmony_ci 7268c2ecf20Sopenharmony_ci if (conn->type != CONNECT_TYPE_TCP || !tcp) 7278c2ecf20Sopenharmony_ci return false; 7288c2ecf20Sopenharmony_ci return head->operations.command == F_CONNECT_REKEY; 7298c2ecf20Sopenharmony_ci} 7308c2ecf20Sopenharmony_ci#endif 7318c2ecf20Sopenharmony_ci 7328c2ecf20Sopenharmony_civoid connection_working_recv_handler(struct connection *conn_impl, void *buf, 7338c2ecf20Sopenharmony_ci void *data, __u32 data_len) 7348c2ecf20Sopenharmony_ci{ 7358c2ecf20Sopenharmony_ci#ifdef CONFIG_HMDFS_FS_ENCRYPTION 7368c2ecf20Sopenharmony_ci if (cmd_update_tls_crypto_key(conn_impl, buf)) { 7378c2ecf20Sopenharmony_ci update_tls_crypto_key(conn_impl, buf, data, data_len); 7388c2ecf20Sopenharmony_ci return; 7398c2ecf20Sopenharmony_ci } 7408c2ecf20Sopenharmony_ci#endif 7418c2ecf20Sopenharmony_ci hmdfs_recv_mesg_callback(conn_impl->node, buf, data); 7428c2ecf20Sopenharmony_ci} 7438c2ecf20Sopenharmony_ci 7448c2ecf20Sopenharmony_cistatic void connection_release(struct kref *ref) 7458c2ecf20Sopenharmony_ci{ 7468c2ecf20Sopenharmony_ci struct tcp_handle *tcp = NULL; 7478c2ecf20Sopenharmony_ci struct connection *conn = container_of(ref, struct connection, ref_cnt); 7488c2ecf20Sopenharmony_ci 7498c2ecf20Sopenharmony_ci hmdfs_info("connection release"); 7508c2ecf20Sopenharmony_ci memset(conn->master_key, 0, HMDFS_KEY_SIZE); 7518c2ecf20Sopenharmony_ci memset(conn->send_key, 0, HMDFS_KEY_SIZE); 7528c2ecf20Sopenharmony_ci memset(conn->recv_key, 0, HMDFS_KEY_SIZE); 7538c2ecf20Sopenharmony_ci if (conn->close) 7548c2ecf20Sopenharmony_ci conn->close(conn); 7558c2ecf20Sopenharmony_ci tcp = conn->connect_handle; 7568c2ecf20Sopenharmony_ci crypto_free_aead(conn->tfm); 7578c2ecf20Sopenharmony_ci // need to check and test: fput(tcp->sock->file); 7588c2ecf20Sopenharmony_ci if (tcp && tcp->sock) { 7598c2ecf20Sopenharmony_ci hmdfs_info("connection release: fd = %d, refcount %ld", tcp->fd, 7608c2ecf20Sopenharmony_ci file_count(tcp->sock->file)); 7618c2ecf20Sopenharmony_ci sockfd_put(tcp->sock); 7628c2ecf20Sopenharmony_ci } 7638c2ecf20Sopenharmony_ci if (tcp && tcp->recv_cache) 7648c2ecf20Sopenharmony_ci kmem_cache_destroy(tcp->recv_cache); 7658c2ecf20Sopenharmony_ci 7668c2ecf20Sopenharmony_ci if (!list_empty(&conn->list)) { 7678c2ecf20Sopenharmony_ci mutex_lock(&conn->node->conn_impl_list_lock); 7688c2ecf20Sopenharmony_ci list_del(&conn->list); 7698c2ecf20Sopenharmony_ci mutex_unlock(&conn->node->conn_impl_list_lock); 7708c2ecf20Sopenharmony_ci /* 7718c2ecf20Sopenharmony_ci * wakup hmdfs_disconnect_node to check 7728c2ecf20Sopenharmony_ci * conn_deleting_list if empty. 7738c2ecf20Sopenharmony_ci */ 7748c2ecf20Sopenharmony_ci wake_up_interruptible(&conn->node->deleting_list_wq); 7758c2ecf20Sopenharmony_ci } 7768c2ecf20Sopenharmony_ci 7778c2ecf20Sopenharmony_ci kfree(tcp); 7788c2ecf20Sopenharmony_ci kfree(conn); 7798c2ecf20Sopenharmony_ci} 7808c2ecf20Sopenharmony_ci 7818c2ecf20Sopenharmony_cistatic void hmdfs_peer_release(struct kref *ref) 7828c2ecf20Sopenharmony_ci{ 7838c2ecf20Sopenharmony_ci struct hmdfs_peer *peer = container_of(ref, struct hmdfs_peer, ref_cnt); 7848c2ecf20Sopenharmony_ci struct mutex *lock = &peer->sbi->connections.node_lock; 7858c2ecf20Sopenharmony_ci 7868c2ecf20Sopenharmony_ci if (!list_empty(&peer->list)) 7878c2ecf20Sopenharmony_ci hmdfs_info("releasing a on-sbi peer: device_id %llu ", 7888c2ecf20Sopenharmony_ci peer->device_id); 7898c2ecf20Sopenharmony_ci else 7908c2ecf20Sopenharmony_ci hmdfs_info("releasing a redundant peer: device_id %llu ", 7918c2ecf20Sopenharmony_ci peer->device_id); 7928c2ecf20Sopenharmony_ci 7938c2ecf20Sopenharmony_ci cancel_delayed_work_sync(&peer->evt_dwork); 7948c2ecf20Sopenharmony_ci list_del(&peer->list); 7958c2ecf20Sopenharmony_ci idr_destroy(&peer->msg_idr); 7968c2ecf20Sopenharmony_ci idr_destroy(&peer->file_id_idr); 7978c2ecf20Sopenharmony_ci flush_workqueue(peer->req_handle_wq); 7988c2ecf20Sopenharmony_ci flush_workqueue(peer->async_wq); 7998c2ecf20Sopenharmony_ci flush_workqueue(peer->retry_wb_wq); 8008c2ecf20Sopenharmony_ci destroy_workqueue(peer->dentry_wq); 8018c2ecf20Sopenharmony_ci destroy_workqueue(peer->req_handle_wq); 8028c2ecf20Sopenharmony_ci destroy_workqueue(peer->async_wq); 8038c2ecf20Sopenharmony_ci destroy_workqueue(peer->retry_wb_wq); 8048c2ecf20Sopenharmony_ci destroy_workqueue(peer->reget_conn_wq); 8058c2ecf20Sopenharmony_ci kfree(peer); 8068c2ecf20Sopenharmony_ci mutex_unlock(lock); 8078c2ecf20Sopenharmony_ci} 8088c2ecf20Sopenharmony_ci 8098c2ecf20Sopenharmony_civoid connection_put(struct connection *conn) 8108c2ecf20Sopenharmony_ci{ 8118c2ecf20Sopenharmony_ci struct mutex *lock = &conn->ref_lock; 8128c2ecf20Sopenharmony_ci 8138c2ecf20Sopenharmony_ci kref_put_mutex(&conn->ref_cnt, connection_release, lock); 8148c2ecf20Sopenharmony_ci} 8158c2ecf20Sopenharmony_ci 8168c2ecf20Sopenharmony_civoid peer_put(struct hmdfs_peer *peer) 8178c2ecf20Sopenharmony_ci{ 8188c2ecf20Sopenharmony_ci struct mutex *lock = &peer->sbi->connections.node_lock; 8198c2ecf20Sopenharmony_ci 8208c2ecf20Sopenharmony_ci kref_put_mutex(&peer->ref_cnt, hmdfs_peer_release, lock); 8218c2ecf20Sopenharmony_ci} 8228c2ecf20Sopenharmony_ci 8238c2ecf20Sopenharmony_cistatic void hmdfs_dump_deleting_list(struct hmdfs_peer *node) 8248c2ecf20Sopenharmony_ci{ 8258c2ecf20Sopenharmony_ci struct connection *con = NULL; 8268c2ecf20Sopenharmony_ci struct tcp_handle *tcp = NULL; 8278c2ecf20Sopenharmony_ci int count = 0; 8288c2ecf20Sopenharmony_ci 8298c2ecf20Sopenharmony_ci mutex_lock(&node->conn_impl_list_lock); 8308c2ecf20Sopenharmony_ci list_for_each_entry(con, &node->conn_deleting_list, list) { 8318c2ecf20Sopenharmony_ci tcp = con->connect_handle; 8328c2ecf20Sopenharmony_ci hmdfs_info("deleting list %d:device_id %llu tcp_fd %d refcnt %d", 8338c2ecf20Sopenharmony_ci count, node->device_id, tcp ? tcp->fd : -1, 8348c2ecf20Sopenharmony_ci kref_read(&con->ref_cnt)); 8358c2ecf20Sopenharmony_ci count++; 8368c2ecf20Sopenharmony_ci } 8378c2ecf20Sopenharmony_ci mutex_unlock(&node->conn_impl_list_lock); 8388c2ecf20Sopenharmony_ci} 8398c2ecf20Sopenharmony_ci 8408c2ecf20Sopenharmony_cistatic bool hmdfs_conn_deleting_list_empty(struct hmdfs_peer *node) 8418c2ecf20Sopenharmony_ci{ 8428c2ecf20Sopenharmony_ci bool empty = false; 8438c2ecf20Sopenharmony_ci 8448c2ecf20Sopenharmony_ci mutex_lock(&node->conn_impl_list_lock); 8458c2ecf20Sopenharmony_ci empty = list_empty(&node->conn_deleting_list); 8468c2ecf20Sopenharmony_ci mutex_unlock(&node->conn_impl_list_lock); 8478c2ecf20Sopenharmony_ci 8488c2ecf20Sopenharmony_ci return empty; 8498c2ecf20Sopenharmony_ci} 8508c2ecf20Sopenharmony_ci 8518c2ecf20Sopenharmony_civoid hmdfs_disconnect_node(struct hmdfs_peer *node) 8528c2ecf20Sopenharmony_ci{ 8538c2ecf20Sopenharmony_ci LIST_HEAD(local_conns); 8548c2ecf20Sopenharmony_ci struct connection *conn_impl = NULL; 8558c2ecf20Sopenharmony_ci struct connection *next = NULL; 8568c2ecf20Sopenharmony_ci struct tcp_handle *tcp = NULL; 8578c2ecf20Sopenharmony_ci 8588c2ecf20Sopenharmony_ci if (unlikely(!node)) 8598c2ecf20Sopenharmony_ci return; 8608c2ecf20Sopenharmony_ci 8618c2ecf20Sopenharmony_ci hmdfs_node_inc_evt_seq(node); 8628c2ecf20Sopenharmony_ci /* Refer to comments in hmdfs_is_node_offlined() */ 8638c2ecf20Sopenharmony_ci smp_mb__after_atomic(); 8648c2ecf20Sopenharmony_ci node->status = NODE_STAT_OFFLINE; 8658c2ecf20Sopenharmony_ci hmdfs_info("Try to disconnect peer: device_id %llu", node->device_id); 8668c2ecf20Sopenharmony_ci 8678c2ecf20Sopenharmony_ci mutex_lock(&node->conn_impl_list_lock); 8688c2ecf20Sopenharmony_ci if (!list_empty(&node->conn_impl_list)) 8698c2ecf20Sopenharmony_ci list_replace_init(&node->conn_impl_list, &local_conns); 8708c2ecf20Sopenharmony_ci mutex_unlock(&node->conn_impl_list_lock); 8718c2ecf20Sopenharmony_ci 8728c2ecf20Sopenharmony_ci list_for_each_entry_safe(conn_impl, next, &local_conns, list) { 8738c2ecf20Sopenharmony_ci tcp = conn_impl->connect_handle; 8748c2ecf20Sopenharmony_ci if (tcp && tcp->sock) { 8758c2ecf20Sopenharmony_ci kernel_sock_shutdown(tcp->sock, SHUT_RDWR); 8768c2ecf20Sopenharmony_ci hmdfs_info("shudown sock: fd = %d, refcount %ld", 8778c2ecf20Sopenharmony_ci tcp->fd, file_count(tcp->sock->file)); 8788c2ecf20Sopenharmony_ci } 8798c2ecf20Sopenharmony_ci if (tcp) 8808c2ecf20Sopenharmony_ci tcp->fd = INVALID_SOCKET_FD; 8818c2ecf20Sopenharmony_ci 8828c2ecf20Sopenharmony_ci tcp_close_socket(tcp); 8838c2ecf20Sopenharmony_ci list_del_init(&conn_impl->list); 8848c2ecf20Sopenharmony_ci 8858c2ecf20Sopenharmony_ci connection_put(conn_impl); 8868c2ecf20Sopenharmony_ci } 8878c2ecf20Sopenharmony_ci 8888c2ecf20Sopenharmony_ci if (wait_event_interruptible_timeout(node->deleting_list_wq, 8898c2ecf20Sopenharmony_ci hmdfs_conn_deleting_list_empty(node), 8908c2ecf20Sopenharmony_ci HMDFS_WAIT_CONN_RELEASE) <= 0) 8918c2ecf20Sopenharmony_ci hmdfs_dump_deleting_list(node); 8928c2ecf20Sopenharmony_ci 8938c2ecf20Sopenharmony_ci /* wait all request process end */ 8948c2ecf20Sopenharmony_ci spin_lock(&node->idr_lock); 8958c2ecf20Sopenharmony_ci while (node->msg_idr_process) { 8968c2ecf20Sopenharmony_ci spin_unlock(&node->idr_lock); 8978c2ecf20Sopenharmony_ci usleep_range(HMDFS_WAIT_REQUEST_END_MIN, 8988c2ecf20Sopenharmony_ci HMDFS_WAIT_REQUEST_END_MAX); 8998c2ecf20Sopenharmony_ci spin_lock(&node->idr_lock); 9008c2ecf20Sopenharmony_ci } 9018c2ecf20Sopenharmony_ci spin_unlock(&node->idr_lock); 9028c2ecf20Sopenharmony_ci 9038c2ecf20Sopenharmony_ci hmdfs_queue_raw_node_evt(node, RAW_NODE_EVT_OFF); 9048c2ecf20Sopenharmony_ci} 9058c2ecf20Sopenharmony_ci 9068c2ecf20Sopenharmony_cistatic void hmdfs_run_simple_evt_cb(struct hmdfs_peer *node, int evt) 9078c2ecf20Sopenharmony_ci{ 9088c2ecf20Sopenharmony_ci unsigned int seq = hmdfs_node_inc_evt_seq(node); 9098c2ecf20Sopenharmony_ci 9108c2ecf20Sopenharmony_ci mutex_lock(&node->seq_lock); 9118c2ecf20Sopenharmony_ci hmdfs_node_call_evt_cb(node, evt, true, seq); 9128c2ecf20Sopenharmony_ci mutex_unlock(&node->seq_lock); 9138c2ecf20Sopenharmony_ci} 9148c2ecf20Sopenharmony_ci 9158c2ecf20Sopenharmony_cistatic void hmdfs_del_peer(struct hmdfs_peer *node) 9168c2ecf20Sopenharmony_ci{ 9178c2ecf20Sopenharmony_ci /* 9188c2ecf20Sopenharmony_ci * No need for offline evt cb, because all files must 9198c2ecf20Sopenharmony_ci * have been flushed and closed, else the filesystem 9208c2ecf20Sopenharmony_ci * will be un-mountable. 9218c2ecf20Sopenharmony_ci */ 9228c2ecf20Sopenharmony_ci cancel_delayed_work_sync(&node->evt_dwork); 9238c2ecf20Sopenharmony_ci 9248c2ecf20Sopenharmony_ci hmdfs_run_simple_evt_cb(node, NODE_EVT_DEL); 9258c2ecf20Sopenharmony_ci 9268c2ecf20Sopenharmony_ci hmdfs_release_peer_sysfs(node); 9278c2ecf20Sopenharmony_ci 9288c2ecf20Sopenharmony_ci flush_workqueue(node->reget_conn_wq); 9298c2ecf20Sopenharmony_ci peer_put(node); 9308c2ecf20Sopenharmony_ci} 9318c2ecf20Sopenharmony_ci 9328c2ecf20Sopenharmony_civoid hmdfs_connections_stop(struct hmdfs_sb_info *sbi) 9338c2ecf20Sopenharmony_ci{ 9348c2ecf20Sopenharmony_ci struct hmdfs_peer *node = NULL; 9358c2ecf20Sopenharmony_ci struct hmdfs_peer *con_tmp = NULL; 9368c2ecf20Sopenharmony_ci 9378c2ecf20Sopenharmony_ci mutex_lock(&sbi->connections.node_lock); 9388c2ecf20Sopenharmony_ci list_for_each_entry_safe(node, con_tmp, &sbi->connections.node_list, 9398c2ecf20Sopenharmony_ci list) { 9408c2ecf20Sopenharmony_ci mutex_unlock(&sbi->connections.node_lock); 9418c2ecf20Sopenharmony_ci hmdfs_disconnect_node(node); 9428c2ecf20Sopenharmony_ci hmdfs_del_peer(node); 9438c2ecf20Sopenharmony_ci mutex_lock(&sbi->connections.node_lock); 9448c2ecf20Sopenharmony_ci } 9458c2ecf20Sopenharmony_ci mutex_unlock(&sbi->connections.node_lock); 9468c2ecf20Sopenharmony_ci} 9478c2ecf20Sopenharmony_ci 9488c2ecf20Sopenharmony_cistruct connection *get_conn_impl(struct hmdfs_peer *node, int connect_type) 9498c2ecf20Sopenharmony_ci{ 9508c2ecf20Sopenharmony_ci struct connection *conn_impl = NULL; 9518c2ecf20Sopenharmony_ci 9528c2ecf20Sopenharmony_ci if (!node) 9538c2ecf20Sopenharmony_ci return NULL; 9548c2ecf20Sopenharmony_ci mutex_lock(&node->conn_impl_list_lock); 9558c2ecf20Sopenharmony_ci list_for_each_entry(conn_impl, &node->conn_impl_list, list) { 9568c2ecf20Sopenharmony_ci if (conn_impl->type == connect_type && 9578c2ecf20Sopenharmony_ci conn_impl->status == CONNECT_STAT_WORKING) { 9588c2ecf20Sopenharmony_ci connection_get(conn_impl); 9598c2ecf20Sopenharmony_ci mutex_unlock(&node->conn_impl_list_lock); 9608c2ecf20Sopenharmony_ci return conn_impl; 9618c2ecf20Sopenharmony_ci } 9628c2ecf20Sopenharmony_ci } 9638c2ecf20Sopenharmony_ci mutex_unlock(&node->conn_impl_list_lock); 9648c2ecf20Sopenharmony_ci hmdfs_err_ratelimited("device %llu not find connection, type %d", 9658c2ecf20Sopenharmony_ci node->device_id, connect_type); 9668c2ecf20Sopenharmony_ci return NULL; 9678c2ecf20Sopenharmony_ci} 9688c2ecf20Sopenharmony_ci 9698c2ecf20Sopenharmony_civoid set_conn_sock_quickack(struct hmdfs_peer *node) 9708c2ecf20Sopenharmony_ci{ 9718c2ecf20Sopenharmony_ci struct connection *conn_impl = NULL; 9728c2ecf20Sopenharmony_ci struct tcp_handle *tcp = NULL; 9738c2ecf20Sopenharmony_ci int option = 1; 9748c2ecf20Sopenharmony_ci 9758c2ecf20Sopenharmony_ci if (!node) 9768c2ecf20Sopenharmony_ci return; 9778c2ecf20Sopenharmony_ci mutex_lock(&node->conn_impl_list_lock); 9788c2ecf20Sopenharmony_ci list_for_each_entry(conn_impl, &node->conn_impl_list, list) { 9798c2ecf20Sopenharmony_ci if (conn_impl->type == CONNECT_TYPE_TCP && 9808c2ecf20Sopenharmony_ci conn_impl->status == CONNECT_STAT_WORKING && 9818c2ecf20Sopenharmony_ci conn_impl->connect_handle) { 9828c2ecf20Sopenharmony_ci tcp = (struct tcp_handle *)(conn_impl->connect_handle); 9838c2ecf20Sopenharmony_ci tcp_sock_set_quickack(tcp->sock->sk, option); 9848c2ecf20Sopenharmony_ci } 9858c2ecf20Sopenharmony_ci } 9868c2ecf20Sopenharmony_ci mutex_unlock(&node->conn_impl_list_lock); 9878c2ecf20Sopenharmony_ci} 9888c2ecf20Sopenharmony_ci 9898c2ecf20Sopenharmony_cistruct hmdfs_peer *hmdfs_lookup_from_devid(struct hmdfs_sb_info *sbi, 9908c2ecf20Sopenharmony_ci uint64_t device_id) 9918c2ecf20Sopenharmony_ci{ 9928c2ecf20Sopenharmony_ci struct hmdfs_peer *con = NULL; 9938c2ecf20Sopenharmony_ci struct hmdfs_peer *lookup = NULL; 9948c2ecf20Sopenharmony_ci 9958c2ecf20Sopenharmony_ci if (!sbi) 9968c2ecf20Sopenharmony_ci return NULL; 9978c2ecf20Sopenharmony_ci mutex_lock(&sbi->connections.node_lock); 9988c2ecf20Sopenharmony_ci list_for_each_entry(con, &sbi->connections.node_list, list) { 9998c2ecf20Sopenharmony_ci if (con->status != NODE_STAT_ONLINE || 10008c2ecf20Sopenharmony_ci con->device_id != device_id) 10018c2ecf20Sopenharmony_ci continue; 10028c2ecf20Sopenharmony_ci lookup = con; 10038c2ecf20Sopenharmony_ci peer_get(lookup); 10048c2ecf20Sopenharmony_ci break; 10058c2ecf20Sopenharmony_ci } 10068c2ecf20Sopenharmony_ci mutex_unlock(&sbi->connections.node_lock); 10078c2ecf20Sopenharmony_ci return lookup; 10088c2ecf20Sopenharmony_ci} 10098c2ecf20Sopenharmony_ci 10108c2ecf20Sopenharmony_cistruct hmdfs_peer *hmdfs_lookup_from_cid(struct hmdfs_sb_info *sbi, 10118c2ecf20Sopenharmony_ci uint8_t *cid) 10128c2ecf20Sopenharmony_ci{ 10138c2ecf20Sopenharmony_ci struct hmdfs_peer *con = NULL; 10148c2ecf20Sopenharmony_ci struct hmdfs_peer *lookup = NULL; 10158c2ecf20Sopenharmony_ci 10168c2ecf20Sopenharmony_ci if (!sbi) 10178c2ecf20Sopenharmony_ci return NULL; 10188c2ecf20Sopenharmony_ci mutex_lock(&sbi->connections.node_lock); 10198c2ecf20Sopenharmony_ci list_for_each_entry(con, &sbi->connections.node_list, list) { 10208c2ecf20Sopenharmony_ci if (strncmp(con->cid, cid, HMDFS_CID_SIZE) != 0) 10218c2ecf20Sopenharmony_ci continue; 10228c2ecf20Sopenharmony_ci lookup = con; 10238c2ecf20Sopenharmony_ci peer_get(lookup); 10248c2ecf20Sopenharmony_ci break; 10258c2ecf20Sopenharmony_ci } 10268c2ecf20Sopenharmony_ci mutex_unlock(&sbi->connections.node_lock); 10278c2ecf20Sopenharmony_ci return lookup; 10288c2ecf20Sopenharmony_ci} 10298c2ecf20Sopenharmony_ci 10308c2ecf20Sopenharmony_cistatic struct hmdfs_peer *lookup_peer_by_cid_unsafe(struct hmdfs_sb_info *sbi, 10318c2ecf20Sopenharmony_ci uint8_t *cid) 10328c2ecf20Sopenharmony_ci{ 10338c2ecf20Sopenharmony_ci struct hmdfs_peer *node = NULL; 10348c2ecf20Sopenharmony_ci 10358c2ecf20Sopenharmony_ci list_for_each_entry(node, &sbi->connections.node_list, list) 10368c2ecf20Sopenharmony_ci if (!strncmp(node->cid, cid, HMDFS_CID_SIZE)) { 10378c2ecf20Sopenharmony_ci peer_get(node); 10388c2ecf20Sopenharmony_ci return node; 10398c2ecf20Sopenharmony_ci } 10408c2ecf20Sopenharmony_ci return NULL; 10418c2ecf20Sopenharmony_ci} 10428c2ecf20Sopenharmony_ci 10438c2ecf20Sopenharmony_cistatic struct hmdfs_peer *add_peer_unsafe(struct hmdfs_sb_info *sbi, 10448c2ecf20Sopenharmony_ci struct hmdfs_peer *peer2add) 10458c2ecf20Sopenharmony_ci{ 10468c2ecf20Sopenharmony_ci struct hmdfs_peer *peer; 10478c2ecf20Sopenharmony_ci int err; 10488c2ecf20Sopenharmony_ci 10498c2ecf20Sopenharmony_ci peer = lookup_peer_by_cid_unsafe(sbi, peer2add->cid); 10508c2ecf20Sopenharmony_ci if (peer) 10518c2ecf20Sopenharmony_ci return peer; 10528c2ecf20Sopenharmony_ci 10538c2ecf20Sopenharmony_ci err = hmdfs_register_peer_sysfs(sbi, peer2add); 10548c2ecf20Sopenharmony_ci if (err) { 10558c2ecf20Sopenharmony_ci hmdfs_err("register peer %llu sysfs err %d", 10568c2ecf20Sopenharmony_ci peer2add->device_id, err); 10578c2ecf20Sopenharmony_ci return ERR_PTR(err); 10588c2ecf20Sopenharmony_ci } 10598c2ecf20Sopenharmony_ci list_add_tail(&peer2add->list, &sbi->connections.node_list); 10608c2ecf20Sopenharmony_ci peer_get(peer2add); 10618c2ecf20Sopenharmony_ci hmdfs_run_simple_evt_cb(peer2add, NODE_EVT_ADD); 10628c2ecf20Sopenharmony_ci return peer2add; 10638c2ecf20Sopenharmony_ci} 10648c2ecf20Sopenharmony_ci 10658c2ecf20Sopenharmony_cistatic struct hmdfs_peer *alloc_peer(struct hmdfs_sb_info *sbi, uint8_t *cid, 10668c2ecf20Sopenharmony_ci uint32_t devsl) 10678c2ecf20Sopenharmony_ci{ 10688c2ecf20Sopenharmony_ci struct hmdfs_peer *node = kzalloc(sizeof(*node), GFP_KERNEL); 10698c2ecf20Sopenharmony_ci 10708c2ecf20Sopenharmony_ci if (!node) 10718c2ecf20Sopenharmony_ci return NULL; 10728c2ecf20Sopenharmony_ci 10738c2ecf20Sopenharmony_ci node->device_id = (u32)atomic_inc_return(&sbi->connections.conn_seq); 10748c2ecf20Sopenharmony_ci 10758c2ecf20Sopenharmony_ci node->async_wq = alloc_workqueue("dfs_async%u_%llu", WQ_MEM_RECLAIM, 0, 10768c2ecf20Sopenharmony_ci sbi->seq, node->device_id); 10778c2ecf20Sopenharmony_ci if (!node->async_wq) { 10788c2ecf20Sopenharmony_ci hmdfs_err("Failed to alloc async wq"); 10798c2ecf20Sopenharmony_ci goto out_err; 10808c2ecf20Sopenharmony_ci } 10818c2ecf20Sopenharmony_ci node->req_handle_wq = alloc_workqueue("dfs_req%u_%llu", 10828c2ecf20Sopenharmony_ci WQ_UNBOUND | WQ_MEM_RECLAIM, 10838c2ecf20Sopenharmony_ci sbi->async_req_max_active, 10848c2ecf20Sopenharmony_ci sbi->seq, node->device_id); 10858c2ecf20Sopenharmony_ci if (!node->req_handle_wq) { 10868c2ecf20Sopenharmony_ci hmdfs_err("Failed to alloc req wq"); 10878c2ecf20Sopenharmony_ci goto out_err; 10888c2ecf20Sopenharmony_ci } 10898c2ecf20Sopenharmony_ci node->dentry_wq = alloc_workqueue("dfs_dentry%u_%llu", 10908c2ecf20Sopenharmony_ci WQ_UNBOUND | WQ_MEM_RECLAIM, 10918c2ecf20Sopenharmony_ci 0, sbi->seq, node->device_id); 10928c2ecf20Sopenharmony_ci if (!node->dentry_wq) { 10938c2ecf20Sopenharmony_ci hmdfs_err("Failed to alloc dentry wq"); 10948c2ecf20Sopenharmony_ci goto out_err; 10958c2ecf20Sopenharmony_ci } 10968c2ecf20Sopenharmony_ci node->retry_wb_wq = alloc_workqueue("dfs_rwb%u_%llu", 10978c2ecf20Sopenharmony_ci WQ_UNBOUND | WQ_MEM_RECLAIM, 10988c2ecf20Sopenharmony_ci HMDFS_RETRY_WB_WQ_MAX_ACTIVE, 10998c2ecf20Sopenharmony_ci sbi->seq, node->device_id); 11008c2ecf20Sopenharmony_ci if (!node->retry_wb_wq) { 11018c2ecf20Sopenharmony_ci hmdfs_err("Failed to alloc retry writeback wq"); 11028c2ecf20Sopenharmony_ci goto out_err; 11038c2ecf20Sopenharmony_ci } 11048c2ecf20Sopenharmony_ci node->reget_conn_wq = alloc_workqueue("dfs_regetcon%u_%llu", 11058c2ecf20Sopenharmony_ci WQ_UNBOUND, 0, 11068c2ecf20Sopenharmony_ci sbi->seq, node->device_id); 11078c2ecf20Sopenharmony_ci if (!node->reget_conn_wq) { 11088c2ecf20Sopenharmony_ci hmdfs_err("Failed to alloc reget conn wq"); 11098c2ecf20Sopenharmony_ci goto out_err; 11108c2ecf20Sopenharmony_ci } 11118c2ecf20Sopenharmony_ci INIT_LIST_HEAD(&node->conn_impl_list); 11128c2ecf20Sopenharmony_ci mutex_init(&node->conn_impl_list_lock); 11138c2ecf20Sopenharmony_ci INIT_LIST_HEAD(&node->conn_deleting_list); 11148c2ecf20Sopenharmony_ci init_waitqueue_head(&node->deleting_list_wq); 11158c2ecf20Sopenharmony_ci idr_init(&node->msg_idr); 11168c2ecf20Sopenharmony_ci spin_lock_init(&node->idr_lock); 11178c2ecf20Sopenharmony_ci idr_init(&node->file_id_idr); 11188c2ecf20Sopenharmony_ci spin_lock_init(&node->file_id_lock); 11198c2ecf20Sopenharmony_ci INIT_LIST_HEAD(&node->list); 11208c2ecf20Sopenharmony_ci kref_init(&node->ref_cnt); 11218c2ecf20Sopenharmony_ci node->owner = sbi->seq; 11228c2ecf20Sopenharmony_ci node->sbi = sbi; 11238c2ecf20Sopenharmony_ci node->version = HMDFS_VERSION; 11248c2ecf20Sopenharmony_ci node->status = NODE_STAT_SHAKING; 11258c2ecf20Sopenharmony_ci node->conn_time = jiffies; 11268c2ecf20Sopenharmony_ci memcpy(node->cid, cid, HMDFS_CID_SIZE); 11278c2ecf20Sopenharmony_ci atomic64_set(&node->sb_dirty_count, 0); 11288c2ecf20Sopenharmony_ci node->fid_cookie = 0; 11298c2ecf20Sopenharmony_ci atomic_set(&node->evt_seq, 0); 11308c2ecf20Sopenharmony_ci mutex_init(&node->seq_lock); 11318c2ecf20Sopenharmony_ci mutex_init(&node->offline_cb_lock); 11328c2ecf20Sopenharmony_ci mutex_init(&node->evt_lock); 11338c2ecf20Sopenharmony_ci node->pending_evt = RAW_NODE_EVT_NR; 11348c2ecf20Sopenharmony_ci node->last_evt = RAW_NODE_EVT_NR; 11358c2ecf20Sopenharmony_ci node->cur_evt[0] = RAW_NODE_EVT_NR; 11368c2ecf20Sopenharmony_ci node->cur_evt[1] = RAW_NODE_EVT_NR; 11378c2ecf20Sopenharmony_ci node->seq_wr_idx = (unsigned char)UINT_MAX; 11388c2ecf20Sopenharmony_ci node->seq_rd_idx = node->seq_wr_idx; 11398c2ecf20Sopenharmony_ci INIT_DELAYED_WORK(&node->evt_dwork, hmdfs_node_evt_work); 11408c2ecf20Sopenharmony_ci node->msg_idr_process = 0; 11418c2ecf20Sopenharmony_ci node->offline_start = false; 11428c2ecf20Sopenharmony_ci spin_lock_init(&node->wr_opened_inode_lock); 11438c2ecf20Sopenharmony_ci INIT_LIST_HEAD(&node->wr_opened_inode_list); 11448c2ecf20Sopenharmony_ci spin_lock_init(&node->stashed_inode_lock); 11458c2ecf20Sopenharmony_ci node->stashed_inode_nr = 0; 11468c2ecf20Sopenharmony_ci atomic_set(&node->rebuild_inode_status_nr, 0); 11478c2ecf20Sopenharmony_ci init_waitqueue_head(&node->rebuild_inode_status_wq); 11488c2ecf20Sopenharmony_ci INIT_LIST_HEAD(&node->stashed_inode_list); 11498c2ecf20Sopenharmony_ci node->need_rebuild_stash_list = false; 11508c2ecf20Sopenharmony_ci node->devsl = devsl; 11518c2ecf20Sopenharmony_ci 11528c2ecf20Sopenharmony_ci return node; 11538c2ecf20Sopenharmony_ci 11548c2ecf20Sopenharmony_ciout_err: 11558c2ecf20Sopenharmony_ci if (node->async_wq) { 11568c2ecf20Sopenharmony_ci destroy_workqueue(node->async_wq); 11578c2ecf20Sopenharmony_ci node->async_wq = NULL; 11588c2ecf20Sopenharmony_ci } 11598c2ecf20Sopenharmony_ci if (node->req_handle_wq) { 11608c2ecf20Sopenharmony_ci destroy_workqueue(node->req_handle_wq); 11618c2ecf20Sopenharmony_ci node->req_handle_wq = NULL; 11628c2ecf20Sopenharmony_ci } 11638c2ecf20Sopenharmony_ci if (node->dentry_wq) { 11648c2ecf20Sopenharmony_ci destroy_workqueue(node->dentry_wq); 11658c2ecf20Sopenharmony_ci node->dentry_wq = NULL; 11668c2ecf20Sopenharmony_ci } 11678c2ecf20Sopenharmony_ci if (node->retry_wb_wq) { 11688c2ecf20Sopenharmony_ci destroy_workqueue(node->retry_wb_wq); 11698c2ecf20Sopenharmony_ci node->retry_wb_wq = NULL; 11708c2ecf20Sopenharmony_ci } 11718c2ecf20Sopenharmony_ci if (node->reget_conn_wq) { 11728c2ecf20Sopenharmony_ci destroy_workqueue(node->reget_conn_wq); 11738c2ecf20Sopenharmony_ci node->reget_conn_wq = NULL; 11748c2ecf20Sopenharmony_ci } 11758c2ecf20Sopenharmony_ci kfree(node); 11768c2ecf20Sopenharmony_ci return NULL; 11778c2ecf20Sopenharmony_ci} 11788c2ecf20Sopenharmony_ci 11798c2ecf20Sopenharmony_cistruct hmdfs_peer *hmdfs_get_peer(struct hmdfs_sb_info *sbi, uint8_t *cid, 11808c2ecf20Sopenharmony_ci uint32_t devsl) 11818c2ecf20Sopenharmony_ci{ 11828c2ecf20Sopenharmony_ci struct hmdfs_peer *peer = NULL, *on_sbi_peer = NULL; 11838c2ecf20Sopenharmony_ci 11848c2ecf20Sopenharmony_ci mutex_lock(&sbi->connections.node_lock); 11858c2ecf20Sopenharmony_ci peer = lookup_peer_by_cid_unsafe(sbi, cid); 11868c2ecf20Sopenharmony_ci mutex_unlock(&sbi->connections.node_lock); 11878c2ecf20Sopenharmony_ci if (peer) { 11888c2ecf20Sopenharmony_ci hmdfs_info("Got a existing peer: device_id = %llu", 11898c2ecf20Sopenharmony_ci peer->device_id); 11908c2ecf20Sopenharmony_ci goto out; 11918c2ecf20Sopenharmony_ci } 11928c2ecf20Sopenharmony_ci 11938c2ecf20Sopenharmony_ci peer = alloc_peer(sbi, cid, devsl); 11948c2ecf20Sopenharmony_ci if (unlikely(!peer)) { 11958c2ecf20Sopenharmony_ci hmdfs_info("Failed to alloc a peer"); 11968c2ecf20Sopenharmony_ci goto out; 11978c2ecf20Sopenharmony_ci } 11988c2ecf20Sopenharmony_ci 11998c2ecf20Sopenharmony_ci mutex_lock(&sbi->connections.node_lock); 12008c2ecf20Sopenharmony_ci on_sbi_peer = add_peer_unsafe(sbi, peer); 12018c2ecf20Sopenharmony_ci mutex_unlock(&sbi->connections.node_lock); 12028c2ecf20Sopenharmony_ci if (IS_ERR(on_sbi_peer)) { 12038c2ecf20Sopenharmony_ci peer_put(peer); 12048c2ecf20Sopenharmony_ci peer = NULL; 12058c2ecf20Sopenharmony_ci goto out; 12068c2ecf20Sopenharmony_ci } else if (unlikely(on_sbi_peer != peer)) { 12078c2ecf20Sopenharmony_ci hmdfs_info("Got a existing peer: device_id = %llu", 12088c2ecf20Sopenharmony_ci on_sbi_peer->device_id); 12098c2ecf20Sopenharmony_ci peer_put(peer); 12108c2ecf20Sopenharmony_ci peer = on_sbi_peer; 12118c2ecf20Sopenharmony_ci } else { 12128c2ecf20Sopenharmony_ci hmdfs_info("Got a newly allocated peer: device_id = %llu", 12138c2ecf20Sopenharmony_ci peer->device_id); 12148c2ecf20Sopenharmony_ci } 12158c2ecf20Sopenharmony_ci 12168c2ecf20Sopenharmony_ciout: 12178c2ecf20Sopenharmony_ci return peer; 12188c2ecf20Sopenharmony_ci} 12198c2ecf20Sopenharmony_ci 12208c2ecf20Sopenharmony_cistatic void head_release(struct kref *kref) 12218c2ecf20Sopenharmony_ci{ 12228c2ecf20Sopenharmony_ci struct hmdfs_msg_idr_head *head; 12238c2ecf20Sopenharmony_ci struct hmdfs_peer *con; 12248c2ecf20Sopenharmony_ci 12258c2ecf20Sopenharmony_ci head = (struct hmdfs_msg_idr_head *)container_of(kref, 12268c2ecf20Sopenharmony_ci struct hmdfs_msg_idr_head, ref); 12278c2ecf20Sopenharmony_ci con = head->peer; 12288c2ecf20Sopenharmony_ci idr_remove(&con->msg_idr, head->msg_id); 12298c2ecf20Sopenharmony_ci spin_unlock(&con->idr_lock); 12308c2ecf20Sopenharmony_ci 12318c2ecf20Sopenharmony_ci kfree(head); 12328c2ecf20Sopenharmony_ci} 12338c2ecf20Sopenharmony_ci 12348c2ecf20Sopenharmony_civoid head_put(struct hmdfs_msg_idr_head *head) 12358c2ecf20Sopenharmony_ci{ 12368c2ecf20Sopenharmony_ci kref_put_lock(&head->ref, head_release, &head->peer->idr_lock); 12378c2ecf20Sopenharmony_ci} 12388c2ecf20Sopenharmony_ci 12398c2ecf20Sopenharmony_cistruct hmdfs_msg_idr_head *hmdfs_find_msg_head(struct hmdfs_peer *peer, 12408c2ecf20Sopenharmony_ci int id, struct hmdfs_cmd operations) 12418c2ecf20Sopenharmony_ci{ 12428c2ecf20Sopenharmony_ci struct hmdfs_msg_idr_head *head = NULL; 12438c2ecf20Sopenharmony_ci 12448c2ecf20Sopenharmony_ci spin_lock(&peer->idr_lock); 12458c2ecf20Sopenharmony_ci head = idr_find(&peer->msg_idr, id); 12468c2ecf20Sopenharmony_ci if (head && head->send_cmd_operations.command == operations.command) 12478c2ecf20Sopenharmony_ci kref_get(&head->ref); 12488c2ecf20Sopenharmony_ci else 12498c2ecf20Sopenharmony_ci head = NULL; 12508c2ecf20Sopenharmony_ci spin_unlock(&peer->idr_lock); 12518c2ecf20Sopenharmony_ci 12528c2ecf20Sopenharmony_ci return head; 12538c2ecf20Sopenharmony_ci} 12548c2ecf20Sopenharmony_ci 12558c2ecf20Sopenharmony_ciint hmdfs_alloc_msg_idr(struct hmdfs_peer *peer, enum MSG_IDR_TYPE type, 12568c2ecf20Sopenharmony_ci void *ptr, struct hmdfs_cmd operations) 12578c2ecf20Sopenharmony_ci{ 12588c2ecf20Sopenharmony_ci int ret = -EAGAIN; 12598c2ecf20Sopenharmony_ci struct hmdfs_msg_idr_head *head = ptr; 12608c2ecf20Sopenharmony_ci 12618c2ecf20Sopenharmony_ci idr_preload(GFP_KERNEL); 12628c2ecf20Sopenharmony_ci spin_lock(&peer->idr_lock); 12638c2ecf20Sopenharmony_ci if (!peer->offline_start) 12648c2ecf20Sopenharmony_ci ret = idr_alloc_cyclic(&peer->msg_idr, ptr, 12658c2ecf20Sopenharmony_ci 1, 0, GFP_NOWAIT); 12668c2ecf20Sopenharmony_ci if (ret >= 0) { 12678c2ecf20Sopenharmony_ci kref_init(&head->ref); 12688c2ecf20Sopenharmony_ci head->msg_id = ret; 12698c2ecf20Sopenharmony_ci head->type = type; 12708c2ecf20Sopenharmony_ci head->peer = peer; 12718c2ecf20Sopenharmony_ci head->send_cmd_operations = operations; 12728c2ecf20Sopenharmony_ci peer->msg_idr_process++; 12738c2ecf20Sopenharmony_ci ret = 0; 12748c2ecf20Sopenharmony_ci } 12758c2ecf20Sopenharmony_ci spin_unlock(&peer->idr_lock); 12768c2ecf20Sopenharmony_ci idr_preload_end(); 12778c2ecf20Sopenharmony_ci 12788c2ecf20Sopenharmony_ci return ret; 12798c2ecf20Sopenharmony_ci} 1280