18c2ecf20Sopenharmony_ci// SPDX-License-Identifier: GPL-2.0 28c2ecf20Sopenharmony_ci/* 38c2ecf20Sopenharmony_ci * fs/hmdfs/hmdfs_dentryfile.c 48c2ecf20Sopenharmony_ci * 58c2ecf20Sopenharmony_ci * Copyright (c) 2020-2021 Huawei Device Co., Ltd. 68c2ecf20Sopenharmony_ci */ 78c2ecf20Sopenharmony_ci 88c2ecf20Sopenharmony_ci#include "hmdfs_dentryfile.h" 98c2ecf20Sopenharmony_ci 108c2ecf20Sopenharmony_ci#include <linux/ctype.h> 118c2ecf20Sopenharmony_ci#include <linux/file.h> 128c2ecf20Sopenharmony_ci#include <linux/mount.h> 138c2ecf20Sopenharmony_ci#include <linux/pagemap.h> 148c2ecf20Sopenharmony_ci#include <linux/slab.h> 158c2ecf20Sopenharmony_ci#include <linux/xattr.h> 168c2ecf20Sopenharmony_ci#include <linux/err.h> 178c2ecf20Sopenharmony_ci 188c2ecf20Sopenharmony_ci#include "authority/authentication.h" 198c2ecf20Sopenharmony_ci#include "comm/transport.h" 208c2ecf20Sopenharmony_ci#include "hmdfs_client.h" 218c2ecf20Sopenharmony_ci#include "hmdfs_device_view.h" 228c2ecf20Sopenharmony_ci#include "hmdfs_merge_view.h" 238c2ecf20Sopenharmony_ci 248c2ecf20Sopenharmony_ci/* Hashing code copied from f2fs */ 258c2ecf20Sopenharmony_ci#define HMDFS_HASH_COL_BIT ((0x1ULL) << 63) 268c2ecf20Sopenharmony_ci#define DELTA 0x9E3779B9 278c2ecf20Sopenharmony_ci 288c2ecf20Sopenharmony_cistatic bool is_dot_dotdot(const unsigned char *name, __u32 len) 298c2ecf20Sopenharmony_ci{ 308c2ecf20Sopenharmony_ci if (len == 1 && name[0] == '.') 318c2ecf20Sopenharmony_ci return true; 328c2ecf20Sopenharmony_ci 338c2ecf20Sopenharmony_ci if (len == 2 && name[0] == '.' && name[1] == '.') 348c2ecf20Sopenharmony_ci return true; 358c2ecf20Sopenharmony_ci 368c2ecf20Sopenharmony_ci return false; 378c2ecf20Sopenharmony_ci} 388c2ecf20Sopenharmony_ci 398c2ecf20Sopenharmony_cistatic void str2hashbuf(const unsigned char *msg, size_t len, unsigned int *buf, 408c2ecf20Sopenharmony_ci int num, bool case_sense) 418c2ecf20Sopenharmony_ci{ 428c2ecf20Sopenharmony_ci unsigned int pad, val; 438c2ecf20Sopenharmony_ci int i; 448c2ecf20Sopenharmony_ci unsigned char c; 458c2ecf20Sopenharmony_ci 468c2ecf20Sopenharmony_ci pad = (__u32)len | ((__u32)len << 8); 478c2ecf20Sopenharmony_ci pad |= pad << 16; 488c2ecf20Sopenharmony_ci 498c2ecf20Sopenharmony_ci val = pad; 508c2ecf20Sopenharmony_ci if (len > (size_t)num * 4) 518c2ecf20Sopenharmony_ci len = (size_t)num * 4; 528c2ecf20Sopenharmony_ci for (i = 0; i < len; i++) { 538c2ecf20Sopenharmony_ci if ((i % 4) == 0) 548c2ecf20Sopenharmony_ci val = pad; 558c2ecf20Sopenharmony_ci c = msg[i]; 568c2ecf20Sopenharmony_ci if (!case_sense) 578c2ecf20Sopenharmony_ci c = tolower(c); 588c2ecf20Sopenharmony_ci val = c + (val << 8); 598c2ecf20Sopenharmony_ci if ((i % 4) == 3) { 608c2ecf20Sopenharmony_ci *buf++ = val; 618c2ecf20Sopenharmony_ci val = pad; 628c2ecf20Sopenharmony_ci num--; 638c2ecf20Sopenharmony_ci } 648c2ecf20Sopenharmony_ci } 658c2ecf20Sopenharmony_ci if (--num >= 0) 668c2ecf20Sopenharmony_ci *buf++ = val; 678c2ecf20Sopenharmony_ci while (--num >= 0) 688c2ecf20Sopenharmony_ci *buf++ = pad; 698c2ecf20Sopenharmony_ci} 708c2ecf20Sopenharmony_ci 718c2ecf20Sopenharmony_cistatic void tea_transform(unsigned int buf[4], unsigned int const in[]) 728c2ecf20Sopenharmony_ci{ 738c2ecf20Sopenharmony_ci __u32 sum = 0; 748c2ecf20Sopenharmony_ci __u32 b0 = buf[0], b1 = buf[1]; 758c2ecf20Sopenharmony_ci __u32 a = in[0], b = in[1], c = in[2], d = in[3]; 768c2ecf20Sopenharmony_ci int n = 16; 778c2ecf20Sopenharmony_ci 788c2ecf20Sopenharmony_ci do { 798c2ecf20Sopenharmony_ci sum += DELTA; 808c2ecf20Sopenharmony_ci b0 += ((b1 << 4) + a) ^ (b1 + sum) ^ ((b1 >> 5) + b); 818c2ecf20Sopenharmony_ci b1 += ((b0 << 4) + c) ^ (b0 + sum) ^ ((b0 >> 5) + d); 828c2ecf20Sopenharmony_ci } while (--n); 838c2ecf20Sopenharmony_ci 848c2ecf20Sopenharmony_ci buf[0] += b0; 858c2ecf20Sopenharmony_ci buf[1] += b1; 868c2ecf20Sopenharmony_ci} 878c2ecf20Sopenharmony_ci 888c2ecf20Sopenharmony_ci__u32 hmdfs_dentry_hash(const struct qstr *qstr, bool case_sense) 898c2ecf20Sopenharmony_ci{ 908c2ecf20Sopenharmony_ci __u32 hash; 918c2ecf20Sopenharmony_ci __u32 hmdfs_hash; 928c2ecf20Sopenharmony_ci const unsigned char *p = qstr->name; 938c2ecf20Sopenharmony_ci __u32 len = qstr->len; 948c2ecf20Sopenharmony_ci __u32 in[8], buf[4]; 958c2ecf20Sopenharmony_ci 968c2ecf20Sopenharmony_ci if (is_dot_dotdot(p, len)) 978c2ecf20Sopenharmony_ci return 0; 988c2ecf20Sopenharmony_ci 998c2ecf20Sopenharmony_ci /* Initialize the default seed for the hash checksum functions */ 1008c2ecf20Sopenharmony_ci buf[0] = 0x67452301; 1018c2ecf20Sopenharmony_ci buf[1] = 0xefcdab89; 1028c2ecf20Sopenharmony_ci buf[2] = 0x98badcfe; 1038c2ecf20Sopenharmony_ci buf[3] = 0x10325476; 1048c2ecf20Sopenharmony_ci 1058c2ecf20Sopenharmony_ci while (1) { 1068c2ecf20Sopenharmony_ci str2hashbuf(p, len, in, 4, case_sense); 1078c2ecf20Sopenharmony_ci tea_transform(buf, in); 1088c2ecf20Sopenharmony_ci p += 16; 1098c2ecf20Sopenharmony_ci if (len <= 16) 1108c2ecf20Sopenharmony_ci break; 1118c2ecf20Sopenharmony_ci len -= 16; 1128c2ecf20Sopenharmony_ci } 1138c2ecf20Sopenharmony_ci hash = buf[0]; 1148c2ecf20Sopenharmony_ci hmdfs_hash = hash & ~HMDFS_HASH_COL_BIT; 1158c2ecf20Sopenharmony_ci return hmdfs_hash; 1168c2ecf20Sopenharmony_ci} 1178c2ecf20Sopenharmony_ci 1188c2ecf20Sopenharmony_cistatic atomic_t curr_ino = ATOMIC_INIT(INUNUMBER_START); 1198c2ecf20Sopenharmony_ciint get_inonumber(void) 1208c2ecf20Sopenharmony_ci{ 1218c2ecf20Sopenharmony_ci return atomic_inc_return(&curr_ino); 1228c2ecf20Sopenharmony_ci} 1238c2ecf20Sopenharmony_ci 1248c2ecf20Sopenharmony_cistatic int hmdfs_get_root_dentry_type(struct dentry *dentry, int *is_root) 1258c2ecf20Sopenharmony_ci{ 1268c2ecf20Sopenharmony_ci struct hmdfs_dentry_info *d_info = hmdfs_d(dentry); 1278c2ecf20Sopenharmony_ci 1288c2ecf20Sopenharmony_ci *is_root = 1; 1298c2ecf20Sopenharmony_ci switch (d_info->dentry_type) { 1308c2ecf20Sopenharmony_ci case HMDFS_LAYER_OTHER_LOCAL: 1318c2ecf20Sopenharmony_ci *is_root = 0; 1328c2ecf20Sopenharmony_ci fallthrough; 1338c2ecf20Sopenharmony_ci case HMDFS_LAYER_SECOND_LOCAL: 1348c2ecf20Sopenharmony_ci return HMDFS_LAYER_SECOND_LOCAL; 1358c2ecf20Sopenharmony_ci case HMDFS_LAYER_OTHER_CLOUD: 1368c2ecf20Sopenharmony_ci *is_root = 0; 1378c2ecf20Sopenharmony_ci fallthrough; 1388c2ecf20Sopenharmony_ci case HMDFS_LAYER_SECOND_CLOUD: 1398c2ecf20Sopenharmony_ci return HMDFS_LAYER_SECOND_CLOUD; 1408c2ecf20Sopenharmony_ci case HMDFS_LAYER_OTHER_REMOTE: 1418c2ecf20Sopenharmony_ci *is_root = 0; 1428c2ecf20Sopenharmony_ci fallthrough; 1438c2ecf20Sopenharmony_ci case HMDFS_LAYER_SECOND_REMOTE: 1448c2ecf20Sopenharmony_ci return HMDFS_LAYER_SECOND_REMOTE; 1458c2ecf20Sopenharmony_ci default: 1468c2ecf20Sopenharmony_ci hmdfs_info("Unexpected dentry type %d", d_info->dentry_type); 1478c2ecf20Sopenharmony_ci return -EINVAL; 1488c2ecf20Sopenharmony_ci } 1498c2ecf20Sopenharmony_ci} 1508c2ecf20Sopenharmony_ci 1518c2ecf20Sopenharmony_cistatic int prepend(char **buffer, int *buflen, const char *str, int namelen) 1528c2ecf20Sopenharmony_ci{ 1538c2ecf20Sopenharmony_ci *buflen -= namelen; 1548c2ecf20Sopenharmony_ci if (*buflen < 0) 1558c2ecf20Sopenharmony_ci return -ENAMETOOLONG; 1568c2ecf20Sopenharmony_ci *buffer -= namelen; 1578c2ecf20Sopenharmony_ci memcpy(*buffer, str, namelen); 1588c2ecf20Sopenharmony_ci return 0; 1598c2ecf20Sopenharmony_ci} 1608c2ecf20Sopenharmony_ci 1618c2ecf20Sopenharmony_cistatic int prepend_name(char **buffer, int *buflen, const struct qstr *name) 1628c2ecf20Sopenharmony_ci{ 1638c2ecf20Sopenharmony_ci const char *dname = name->name; 1648c2ecf20Sopenharmony_ci u32 dlen = name->len; 1658c2ecf20Sopenharmony_ci char *p = NULL; 1668c2ecf20Sopenharmony_ci 1678c2ecf20Sopenharmony_ci *buflen -= dlen + 1; 1688c2ecf20Sopenharmony_ci if (*buflen < 0) 1698c2ecf20Sopenharmony_ci return -ENAMETOOLONG; 1708c2ecf20Sopenharmony_ci p = *buffer -= dlen + 1; 1718c2ecf20Sopenharmony_ci *p++ = '/'; 1728c2ecf20Sopenharmony_ci while (dlen--) { 1738c2ecf20Sopenharmony_ci char c = *dname++; 1748c2ecf20Sopenharmony_ci 1758c2ecf20Sopenharmony_ci if (!c) 1768c2ecf20Sopenharmony_ci break; 1778c2ecf20Sopenharmony_ci *p++ = c; 1788c2ecf20Sopenharmony_ci } 1798c2ecf20Sopenharmony_ci return 0; 1808c2ecf20Sopenharmony_ci} 1818c2ecf20Sopenharmony_ci 1828c2ecf20Sopenharmony_cistatic char *hmdfs_dentry_path_raw(struct dentry *d, char *buf, int buflen) 1838c2ecf20Sopenharmony_ci{ 1848c2ecf20Sopenharmony_ci struct dentry *dentry = NULL; 1858c2ecf20Sopenharmony_ci char *end = NULL; 1868c2ecf20Sopenharmony_ci char *retval = NULL; 1878c2ecf20Sopenharmony_ci unsigned int len; 1888c2ecf20Sopenharmony_ci unsigned int seq = 0; 1898c2ecf20Sopenharmony_ci int root_flag = 0; 1908c2ecf20Sopenharmony_ci int error = 0; 1918c2ecf20Sopenharmony_ci struct hmdfs_dentry_info *di = hmdfs_d(d); 1928c2ecf20Sopenharmony_ci int hmdfs_root_dentry_type = 0; 1938c2ecf20Sopenharmony_ci 1948c2ecf20Sopenharmony_ci di->time = jiffies; 1958c2ecf20Sopenharmony_ci hmdfs_root_dentry_type = hmdfs_get_root_dentry_type(d, &root_flag); 1968c2ecf20Sopenharmony_ci if (hmdfs_root_dentry_type < 0) 1978c2ecf20Sopenharmony_ci return NULL; 1988c2ecf20Sopenharmony_ci if (root_flag) { 1998c2ecf20Sopenharmony_ci strcpy(buf, "/"); 2008c2ecf20Sopenharmony_ci return buf; 2018c2ecf20Sopenharmony_ci } 2028c2ecf20Sopenharmony_ci rcu_read_lock(); 2038c2ecf20Sopenharmony_cirestart: 2048c2ecf20Sopenharmony_ci dentry = d; 2058c2ecf20Sopenharmony_ci di = hmdfs_d(dentry); 2068c2ecf20Sopenharmony_ci di->time = jiffies; 2078c2ecf20Sopenharmony_ci end = buf + buflen; 2088c2ecf20Sopenharmony_ci len = buflen; 2098c2ecf20Sopenharmony_ci prepend(&end, &len, "\0", 1); 2108c2ecf20Sopenharmony_ci retval = end - 1; 2118c2ecf20Sopenharmony_ci *retval = '/'; 2128c2ecf20Sopenharmony_ci read_seqbegin_or_lock(&rename_lock, &seq); 2138c2ecf20Sopenharmony_ci while (di->dentry_type != hmdfs_root_dentry_type) { 2148c2ecf20Sopenharmony_ci struct dentry *parent = dentry->d_parent; 2158c2ecf20Sopenharmony_ci 2168c2ecf20Sopenharmony_ci prefetch(parent); 2178c2ecf20Sopenharmony_ci error = prepend_name(&end, &len, &dentry->d_name); 2188c2ecf20Sopenharmony_ci if (error) 2198c2ecf20Sopenharmony_ci break; 2208c2ecf20Sopenharmony_ci retval = end; 2218c2ecf20Sopenharmony_ci dentry = parent; 2228c2ecf20Sopenharmony_ci di = hmdfs_d(dentry); 2238c2ecf20Sopenharmony_ci di->time = jiffies; 2248c2ecf20Sopenharmony_ci } 2258c2ecf20Sopenharmony_ci if (!(seq & 1)) 2268c2ecf20Sopenharmony_ci rcu_read_unlock(); 2278c2ecf20Sopenharmony_ci if (need_seqretry(&rename_lock, seq)) { 2288c2ecf20Sopenharmony_ci seq = 1; 2298c2ecf20Sopenharmony_ci goto restart; 2308c2ecf20Sopenharmony_ci } 2318c2ecf20Sopenharmony_ci done_seqretry(&rename_lock, seq); 2328c2ecf20Sopenharmony_ci if (error) 2338c2ecf20Sopenharmony_ci goto Elong; 2348c2ecf20Sopenharmony_ci return retval; 2358c2ecf20Sopenharmony_ciElong: 2368c2ecf20Sopenharmony_ci return ERR_PTR(-ENAMETOOLONG); 2378c2ecf20Sopenharmony_ci} 2388c2ecf20Sopenharmony_ci 2398c2ecf20Sopenharmony_cichar *hmdfs_get_dentry_relative_path(struct dentry *dentry) 2408c2ecf20Sopenharmony_ci{ 2418c2ecf20Sopenharmony_ci char *final_buf = NULL; 2428c2ecf20Sopenharmony_ci char *buf = NULL; 2438c2ecf20Sopenharmony_ci char *p = NULL; 2448c2ecf20Sopenharmony_ci 2458c2ecf20Sopenharmony_ci buf = kzalloc(PATH_MAX, GFP_KERNEL); 2468c2ecf20Sopenharmony_ci if (!buf) 2478c2ecf20Sopenharmony_ci return NULL; 2488c2ecf20Sopenharmony_ci 2498c2ecf20Sopenharmony_ci final_buf = kzalloc(PATH_MAX, GFP_KERNEL); 2508c2ecf20Sopenharmony_ci if (!final_buf) { 2518c2ecf20Sopenharmony_ci kfree(buf); 2528c2ecf20Sopenharmony_ci return NULL; 2538c2ecf20Sopenharmony_ci } 2548c2ecf20Sopenharmony_ci 2558c2ecf20Sopenharmony_ci /* NULL dentry return root dir */ 2568c2ecf20Sopenharmony_ci if (!dentry) { 2578c2ecf20Sopenharmony_ci strcpy(final_buf, "/"); 2588c2ecf20Sopenharmony_ci kfree(buf); 2598c2ecf20Sopenharmony_ci return final_buf; 2608c2ecf20Sopenharmony_ci } 2618c2ecf20Sopenharmony_ci p = hmdfs_dentry_path_raw(dentry, buf, PATH_MAX); 2628c2ecf20Sopenharmony_ci if (IS_ERR_OR_NULL(p)) { 2638c2ecf20Sopenharmony_ci kfree(buf); 2648c2ecf20Sopenharmony_ci kfree(final_buf); 2658c2ecf20Sopenharmony_ci return NULL; 2668c2ecf20Sopenharmony_ci } 2678c2ecf20Sopenharmony_ci 2688c2ecf20Sopenharmony_ci if (strlen(p) >= PATH_MAX) { 2698c2ecf20Sopenharmony_ci kfree(buf); 2708c2ecf20Sopenharmony_ci kfree(final_buf); 2718c2ecf20Sopenharmony_ci return NULL; 2728c2ecf20Sopenharmony_ci } 2738c2ecf20Sopenharmony_ci strcpy(final_buf, p); 2748c2ecf20Sopenharmony_ci kfree(buf); 2758c2ecf20Sopenharmony_ci return final_buf; 2768c2ecf20Sopenharmony_ci} 2778c2ecf20Sopenharmony_ci 2788c2ecf20Sopenharmony_cistatic char *hmdfs_merge_dentry_path_raw(struct dentry *d, char *buf, int buflen) 2798c2ecf20Sopenharmony_ci{ 2808c2ecf20Sopenharmony_ci struct dentry *dentry = NULL; 2818c2ecf20Sopenharmony_ci char *end = NULL; 2828c2ecf20Sopenharmony_ci char *retval = NULL; 2838c2ecf20Sopenharmony_ci unsigned int len; 2848c2ecf20Sopenharmony_ci unsigned int seq = 0; 2858c2ecf20Sopenharmony_ci int error = 0; 2868c2ecf20Sopenharmony_ci struct hmdfs_dentry_info_merge *mdi = NULL; 2878c2ecf20Sopenharmony_ci 2888c2ecf20Sopenharmony_ci rcu_read_lock(); 2898c2ecf20Sopenharmony_cirestart: 2908c2ecf20Sopenharmony_ci mdi = hmdfs_dm(d); 2918c2ecf20Sopenharmony_ci dentry = d; 2928c2ecf20Sopenharmony_ci end = buf + buflen; 2938c2ecf20Sopenharmony_ci len = buflen; 2948c2ecf20Sopenharmony_ci prepend(&end, &len, "\0", 1); 2958c2ecf20Sopenharmony_ci retval = end - 1; 2968c2ecf20Sopenharmony_ci *retval = '/'; 2978c2ecf20Sopenharmony_ci read_seqbegin_or_lock(&rename_lock, &seq); 2988c2ecf20Sopenharmony_ci while (mdi->dentry_type != HMDFS_LAYER_FIRST_MERGE && 2998c2ecf20Sopenharmony_ci mdi->dentry_type != HMDFS_LAYER_FIRST_MERGE_CLOUD) { 3008c2ecf20Sopenharmony_ci struct dentry *parent = dentry->d_parent; 3018c2ecf20Sopenharmony_ci 3028c2ecf20Sopenharmony_ci prefetch(parent); 3038c2ecf20Sopenharmony_ci error = prepend_name(&end, &len, &dentry->d_name); 3048c2ecf20Sopenharmony_ci if (error) 3058c2ecf20Sopenharmony_ci break; 3068c2ecf20Sopenharmony_ci retval = end; 3078c2ecf20Sopenharmony_ci dentry = parent; 3088c2ecf20Sopenharmony_ci mdi = hmdfs_dm(dentry); 3098c2ecf20Sopenharmony_ci } 3108c2ecf20Sopenharmony_ci if (!(seq & 1)) 3118c2ecf20Sopenharmony_ci rcu_read_unlock(); 3128c2ecf20Sopenharmony_ci if (need_seqretry(&rename_lock, seq)) { 3138c2ecf20Sopenharmony_ci seq = 1; 3148c2ecf20Sopenharmony_ci goto restart; 3158c2ecf20Sopenharmony_ci } 3168c2ecf20Sopenharmony_ci done_seqretry(&rename_lock, seq); 3178c2ecf20Sopenharmony_ci if (error) 3188c2ecf20Sopenharmony_ci goto Elong; 3198c2ecf20Sopenharmony_ci return retval; 3208c2ecf20Sopenharmony_ciElong: 3218c2ecf20Sopenharmony_ci return ERR_PTR(-ENAMETOOLONG); 3228c2ecf20Sopenharmony_ci} 3238c2ecf20Sopenharmony_ci 3248c2ecf20Sopenharmony_cichar *hmdfs_merge_get_dentry_relative_path(struct dentry *dentry) 3258c2ecf20Sopenharmony_ci{ 3268c2ecf20Sopenharmony_ci char *final_buf = NULL; 3278c2ecf20Sopenharmony_ci char *buf = NULL; 3288c2ecf20Sopenharmony_ci char *p = NULL; 3298c2ecf20Sopenharmony_ci 3308c2ecf20Sopenharmony_ci buf = kzalloc(PATH_MAX, GFP_KERNEL); 3318c2ecf20Sopenharmony_ci if (!buf) 3328c2ecf20Sopenharmony_ci return NULL; 3338c2ecf20Sopenharmony_ci 3348c2ecf20Sopenharmony_ci final_buf = kzalloc(PATH_MAX, GFP_KERNEL); 3358c2ecf20Sopenharmony_ci if (!final_buf) { 3368c2ecf20Sopenharmony_ci kfree(buf); 3378c2ecf20Sopenharmony_ci return NULL; 3388c2ecf20Sopenharmony_ci } 3398c2ecf20Sopenharmony_ci 3408c2ecf20Sopenharmony_ci /* NULL dentry return root dir */ 3418c2ecf20Sopenharmony_ci if (!dentry) { 3428c2ecf20Sopenharmony_ci strcpy(final_buf, "/"); 3438c2ecf20Sopenharmony_ci kfree(buf); 3448c2ecf20Sopenharmony_ci return final_buf; 3458c2ecf20Sopenharmony_ci } 3468c2ecf20Sopenharmony_ci p = hmdfs_merge_dentry_path_raw(dentry, buf, PATH_MAX); 3478c2ecf20Sopenharmony_ci if (IS_ERR_OR_NULL(p)) { 3488c2ecf20Sopenharmony_ci kfree(buf); 3498c2ecf20Sopenharmony_ci kfree(final_buf); 3508c2ecf20Sopenharmony_ci return NULL; 3518c2ecf20Sopenharmony_ci } 3528c2ecf20Sopenharmony_ci 3538c2ecf20Sopenharmony_ci if (strlen(p) >= PATH_MAX) { 3548c2ecf20Sopenharmony_ci kfree(buf); 3558c2ecf20Sopenharmony_ci kfree(final_buf); 3568c2ecf20Sopenharmony_ci return NULL; 3578c2ecf20Sopenharmony_ci } 3588c2ecf20Sopenharmony_ci strcpy(final_buf, p); 3598c2ecf20Sopenharmony_ci kfree(buf); 3608c2ecf20Sopenharmony_ci return final_buf; 3618c2ecf20Sopenharmony_ci} 3628c2ecf20Sopenharmony_ci 3638c2ecf20Sopenharmony_cichar *hmdfs_get_dentry_absolute_path(const char *rootdir, 3648c2ecf20Sopenharmony_ci const char *relative_path) 3658c2ecf20Sopenharmony_ci{ 3668c2ecf20Sopenharmony_ci char *buf = 0; 3678c2ecf20Sopenharmony_ci 3688c2ecf20Sopenharmony_ci if (!rootdir || !relative_path) 3698c2ecf20Sopenharmony_ci return NULL; 3708c2ecf20Sopenharmony_ci if (strlen(rootdir) + strlen(relative_path) >= PATH_MAX) 3718c2ecf20Sopenharmony_ci return NULL; 3728c2ecf20Sopenharmony_ci 3738c2ecf20Sopenharmony_ci buf = kzalloc(PATH_MAX, GFP_KERNEL); 3748c2ecf20Sopenharmony_ci if (!buf) 3758c2ecf20Sopenharmony_ci return NULL; 3768c2ecf20Sopenharmony_ci 3778c2ecf20Sopenharmony_ci strcpy(buf, rootdir); 3788c2ecf20Sopenharmony_ci strcat(buf, relative_path); 3798c2ecf20Sopenharmony_ci return buf; 3808c2ecf20Sopenharmony_ci} 3818c2ecf20Sopenharmony_ci 3828c2ecf20Sopenharmony_cichar *hmdfs_connect_path(const char *path, const char *name) 3838c2ecf20Sopenharmony_ci{ 3848c2ecf20Sopenharmony_ci char *buf = 0; 3858c2ecf20Sopenharmony_ci size_t path_len, name_len; 3868c2ecf20Sopenharmony_ci 3878c2ecf20Sopenharmony_ci if (!path || !name) 3888c2ecf20Sopenharmony_ci return NULL; 3898c2ecf20Sopenharmony_ci 3908c2ecf20Sopenharmony_ci path_len = strnlen(path, PATH_MAX); 3918c2ecf20Sopenharmony_ci name_len = strnlen(name, PATH_MAX); 3928c2ecf20Sopenharmony_ci if (path_len + name_len + 1 >= PATH_MAX) 3938c2ecf20Sopenharmony_ci return NULL; 3948c2ecf20Sopenharmony_ci 3958c2ecf20Sopenharmony_ci buf = kzalloc(PATH_MAX, GFP_KERNEL); 3968c2ecf20Sopenharmony_ci if (!buf) 3978c2ecf20Sopenharmony_ci return NULL; 3988c2ecf20Sopenharmony_ci 3998c2ecf20Sopenharmony_ci strncpy(buf, path, path_len); 4008c2ecf20Sopenharmony_ci strcat(buf, "/"); 4018c2ecf20Sopenharmony_ci strncat(buf, name, name_len); 4028c2ecf20Sopenharmony_ci return buf; 4038c2ecf20Sopenharmony_ci} 4048c2ecf20Sopenharmony_ci 4058c2ecf20Sopenharmony_ciint hmdfs_metainfo_read_nocred(struct file *filp, 4068c2ecf20Sopenharmony_ci void *buffer, int size, int bidx) 4078c2ecf20Sopenharmony_ci{ 4088c2ecf20Sopenharmony_ci loff_t pos = get_dentry_group_pos(bidx); 4098c2ecf20Sopenharmony_ci 4108c2ecf20Sopenharmony_ci return kernel_read(filp, buffer, (size_t)size, &pos); 4118c2ecf20Sopenharmony_ci} 4128c2ecf20Sopenharmony_ci 4138c2ecf20Sopenharmony_ciint hmdfs_metainfo_read(struct hmdfs_sb_info *sbi, struct file *filp, 4148c2ecf20Sopenharmony_ci void *buffer, int size, int bidx) 4158c2ecf20Sopenharmony_ci{ 4168c2ecf20Sopenharmony_ci loff_t pos = get_dentry_group_pos(bidx); 4178c2ecf20Sopenharmony_ci 4188c2ecf20Sopenharmony_ci return cache_file_read(sbi, filp, buffer, (size_t)size, &pos); 4198c2ecf20Sopenharmony_ci} 4208c2ecf20Sopenharmony_ci 4218c2ecf20Sopenharmony_ciint hmdfs_metainfo_write(struct hmdfs_sb_info *sbi, struct file *filp, 4228c2ecf20Sopenharmony_ci const void *buffer, int size, int bidx) 4238c2ecf20Sopenharmony_ci{ 4248c2ecf20Sopenharmony_ci loff_t pos = get_dentry_group_pos(bidx); 4258c2ecf20Sopenharmony_ci 4268c2ecf20Sopenharmony_ci return cache_file_write(sbi, filp, buffer, (size_t)size, &pos); 4278c2ecf20Sopenharmony_ci} 4288c2ecf20Sopenharmony_ci 4298c2ecf20Sopenharmony_ci/* for each level */ 4308c2ecf20Sopenharmony_ci/* bucketseq start offset by 0,for example 4318c2ecf20Sopenharmony_ci * level0 bucket0(0) 4328c2ecf20Sopenharmony_ci * level1 bucket0(1) bucket1(2) 4338c2ecf20Sopenharmony_ci * level2 bucket0(3) bucket1(4) bucket2(5) bucket3(6) 4348c2ecf20Sopenharmony_ci * return bucket number. 4358c2ecf20Sopenharmony_ci */ 4368c2ecf20Sopenharmony_ci__u64 get_bucketaddr(unsigned int level, __u64 buckoffset) 4378c2ecf20Sopenharmony_ci{ 4388c2ecf20Sopenharmony_ci __u64 all_level_bucketaddr = 0; 4398c2ecf20Sopenharmony_ci __u64 curlevelmaxbucks; 4408c2ecf20Sopenharmony_ci 4418c2ecf20Sopenharmony_ci if (level >= MAX_BUCKET_LEVEL) { 4428c2ecf20Sopenharmony_ci hmdfs_err("level = %d overflow", level); 4438c2ecf20Sopenharmony_ci return all_level_bucketaddr; 4448c2ecf20Sopenharmony_ci } 4458c2ecf20Sopenharmony_ci curlevelmaxbucks = ((__u64)1 << level); 4468c2ecf20Sopenharmony_ci if (buckoffset >= curlevelmaxbucks) { 4478c2ecf20Sopenharmony_ci hmdfs_err("buckoffset %llu overflow, level %d has %llu buckets max", 4488c2ecf20Sopenharmony_ci buckoffset, level, curlevelmaxbucks); 4498c2ecf20Sopenharmony_ci return all_level_bucketaddr; 4508c2ecf20Sopenharmony_ci } 4518c2ecf20Sopenharmony_ci all_level_bucketaddr = curlevelmaxbucks + buckoffset - 1; 4528c2ecf20Sopenharmony_ci 4538c2ecf20Sopenharmony_ci return all_level_bucketaddr; 4548c2ecf20Sopenharmony_ci} 4558c2ecf20Sopenharmony_ci 4568c2ecf20Sopenharmony_ci__u64 get_bucket_by_level(unsigned int level) 4578c2ecf20Sopenharmony_ci{ 4588c2ecf20Sopenharmony_ci __u64 buckets = 0; 4598c2ecf20Sopenharmony_ci 4608c2ecf20Sopenharmony_ci if (level >= MAX_BUCKET_LEVEL) { 4618c2ecf20Sopenharmony_ci hmdfs_err("level = %d overflow", level); 4628c2ecf20Sopenharmony_ci return buckets; 4638c2ecf20Sopenharmony_ci } 4648c2ecf20Sopenharmony_ci 4658c2ecf20Sopenharmony_ci buckets = ((__u64)1 << level); 4668c2ecf20Sopenharmony_ci return buckets; 4678c2ecf20Sopenharmony_ci} 4688c2ecf20Sopenharmony_ci 4698c2ecf20Sopenharmony_cistatic __u64 get_overall_bucket(unsigned int level) 4708c2ecf20Sopenharmony_ci{ 4718c2ecf20Sopenharmony_ci __u64 buckets = 0; 4728c2ecf20Sopenharmony_ci 4738c2ecf20Sopenharmony_ci if (level >= MAX_BUCKET_LEVEL) { 4748c2ecf20Sopenharmony_ci hmdfs_err("level = %d overflow", level); 4758c2ecf20Sopenharmony_ci return buckets; 4768c2ecf20Sopenharmony_ci } 4778c2ecf20Sopenharmony_ci buckets = ((__u64)1 << (level + 1)) - 1; 4788c2ecf20Sopenharmony_ci return buckets; 4798c2ecf20Sopenharmony_ci} 4808c2ecf20Sopenharmony_ci 4818c2ecf20Sopenharmony_cistatic inline loff_t get_dcache_file_size(unsigned int level) 4828c2ecf20Sopenharmony_ci{ 4838c2ecf20Sopenharmony_ci loff_t buckets = get_overall_bucket(level); 4848c2ecf20Sopenharmony_ci 4858c2ecf20Sopenharmony_ci return buckets * DENTRYGROUP_SIZE * BUCKET_BLOCKS + DENTRYGROUP_HEADER; 4868c2ecf20Sopenharmony_ci} 4878c2ecf20Sopenharmony_ci 4888c2ecf20Sopenharmony_cistatic char *get_relative_path(struct hmdfs_sb_info *sbi, char *from) 4898c2ecf20Sopenharmony_ci{ 4908c2ecf20Sopenharmony_ci char *relative; 4918c2ecf20Sopenharmony_ci 4928c2ecf20Sopenharmony_ci if (strncmp(from, sbi->local_src, strlen(sbi->local_src))) { 4938c2ecf20Sopenharmony_ci hmdfs_warning("orig path do not start with local_src"); 4948c2ecf20Sopenharmony_ci return NULL; 4958c2ecf20Sopenharmony_ci } 4968c2ecf20Sopenharmony_ci relative = from + strlen(sbi->local_src); 4978c2ecf20Sopenharmony_ci if (*relative == '/') 4988c2ecf20Sopenharmony_ci relative++; 4998c2ecf20Sopenharmony_ci return relative; 5008c2ecf20Sopenharmony_ci} 5018c2ecf20Sopenharmony_ci 5028c2ecf20Sopenharmony_cistruct file *hmdfs_get_or_create_dents(struct hmdfs_sb_info *sbi, char *name) 5038c2ecf20Sopenharmony_ci{ 5048c2ecf20Sopenharmony_ci struct path root_path, path; 5058c2ecf20Sopenharmony_ci struct file *filp = NULL; 5068c2ecf20Sopenharmony_ci char *relative; 5078c2ecf20Sopenharmony_ci int err; 5088c2ecf20Sopenharmony_ci 5098c2ecf20Sopenharmony_ci err = kern_path(sbi->local_src, 0, &root_path); 5108c2ecf20Sopenharmony_ci if (err) { 5118c2ecf20Sopenharmony_ci hmdfs_err("kern_path failed err = %d", err); 5128c2ecf20Sopenharmony_ci return NULL; 5138c2ecf20Sopenharmony_ci } 5148c2ecf20Sopenharmony_ci relative = get_relative_path(sbi, name); 5158c2ecf20Sopenharmony_ci if (!relative) { 5168c2ecf20Sopenharmony_ci hmdfs_err("get relative path failed"); 5178c2ecf20Sopenharmony_ci goto err_root_path; 5188c2ecf20Sopenharmony_ci } 5198c2ecf20Sopenharmony_ci err = vfs_path_lookup(root_path.dentry, root_path.mnt, relative, 0, 5208c2ecf20Sopenharmony_ci &path); 5218c2ecf20Sopenharmony_ci if (err) { 5228c2ecf20Sopenharmony_ci hmdfs_err("lookup failed err = %d", err); 5238c2ecf20Sopenharmony_ci goto err_root_path; 5248c2ecf20Sopenharmony_ci } 5258c2ecf20Sopenharmony_ci 5268c2ecf20Sopenharmony_ci filp = hmdfs_server_cache_revalidate(sbi, relative, &path); 5278c2ecf20Sopenharmony_ci if (IS_ERR_OR_NULL(filp)) { 5288c2ecf20Sopenharmony_ci filp = hmdfs_server_rebuild_dents(sbi, &path, NULL, relative); 5298c2ecf20Sopenharmony_ci if (IS_ERR_OR_NULL(filp)) 5308c2ecf20Sopenharmony_ci goto err_lookup_path; 5318c2ecf20Sopenharmony_ci } 5328c2ecf20Sopenharmony_ci 5338c2ecf20Sopenharmony_cierr_lookup_path: 5348c2ecf20Sopenharmony_ci path_put(&path); 5358c2ecf20Sopenharmony_cierr_root_path: 5368c2ecf20Sopenharmony_ci path_put(&root_path); 5378c2ecf20Sopenharmony_ci return filp; 5388c2ecf20Sopenharmony_ci} 5398c2ecf20Sopenharmony_ci 5408c2ecf20Sopenharmony_ci/* read all dentry in target path directory */ 5418c2ecf20Sopenharmony_ciint read_dentry(struct hmdfs_sb_info *sbi, char *file_name, 5428c2ecf20Sopenharmony_ci struct dir_context *ctx) 5438c2ecf20Sopenharmony_ci{ 5448c2ecf20Sopenharmony_ci unsigned long pos = (unsigned long)(ctx->pos); 5458c2ecf20Sopenharmony_ci unsigned long group_id = (pos << (1 + DEV_ID_BIT_NUM)) >> 5468c2ecf20Sopenharmony_ci (POS_BIT_NUM - GROUP_ID_BIT_NUM); 5478c2ecf20Sopenharmony_ci unsigned long offset = pos & OFFSET_BIT_MASK; 5488c2ecf20Sopenharmony_ci struct hmdfs_dentry_group *dentry_group = NULL; 5498c2ecf20Sopenharmony_ci struct file *handler = NULL; 5508c2ecf20Sopenharmony_ci int group_num = 0; 5518c2ecf20Sopenharmony_ci int iterate_result = 0; 5528c2ecf20Sopenharmony_ci int i, j; 5538c2ecf20Sopenharmony_ci const struct cred *saved_cred; 5548c2ecf20Sopenharmony_ci 5558c2ecf20Sopenharmony_ci saved_cred = hmdfs_override_fsids(false); 5568c2ecf20Sopenharmony_ci if (!saved_cred) { 5578c2ecf20Sopenharmony_ci hmdfs_err("prepare cred failed!"); 5588c2ecf20Sopenharmony_ci return -ENOMEM; 5598c2ecf20Sopenharmony_ci } 5608c2ecf20Sopenharmony_ci 5618c2ecf20Sopenharmony_ci 5628c2ecf20Sopenharmony_ci if (!file_name) 5638c2ecf20Sopenharmony_ci return -EINVAL; 5648c2ecf20Sopenharmony_ci 5658c2ecf20Sopenharmony_ci dentry_group = kzalloc(sizeof(*dentry_group), GFP_KERNEL); 5668c2ecf20Sopenharmony_ci if (!dentry_group) 5678c2ecf20Sopenharmony_ci return -ENOMEM; 5688c2ecf20Sopenharmony_ci 5698c2ecf20Sopenharmony_ci handler = hmdfs_get_or_create_dents(sbi, file_name); 5708c2ecf20Sopenharmony_ci if (IS_ERR_OR_NULL(handler)) { 5718c2ecf20Sopenharmony_ci kfree(dentry_group); 5728c2ecf20Sopenharmony_ci return -ENOENT; 5738c2ecf20Sopenharmony_ci } 5748c2ecf20Sopenharmony_ci 5758c2ecf20Sopenharmony_ci group_num = get_dentry_group_cnt(file_inode(handler)); 5768c2ecf20Sopenharmony_ci 5778c2ecf20Sopenharmony_ci for (i = group_id; i < group_num; i++) { 5788c2ecf20Sopenharmony_ci hmdfs_metainfo_read(sbi, handler, dentry_group, 5798c2ecf20Sopenharmony_ci sizeof(struct hmdfs_dentry_group), i); 5808c2ecf20Sopenharmony_ci for (j = offset; j < DENTRY_PER_GROUP; j++) { 5818c2ecf20Sopenharmony_ci int len; 5828c2ecf20Sopenharmony_ci int file_type = 0; 5838c2ecf20Sopenharmony_ci bool is_continue; 5848c2ecf20Sopenharmony_ci 5858c2ecf20Sopenharmony_ci len = le16_to_cpu(dentry_group->nsl[j].namelen); 5868c2ecf20Sopenharmony_ci if (!test_bit_le(j, dentry_group->bitmap) || len == 0) 5878c2ecf20Sopenharmony_ci continue; 5888c2ecf20Sopenharmony_ci 5898c2ecf20Sopenharmony_ci if (S_ISDIR(le16_to_cpu(dentry_group->nsl[j].i_mode))) 5908c2ecf20Sopenharmony_ci file_type = DT_DIR; 5918c2ecf20Sopenharmony_ci else if (S_ISREG(le16_to_cpu( 5928c2ecf20Sopenharmony_ci dentry_group->nsl[j].i_mode))) 5938c2ecf20Sopenharmony_ci file_type = DT_REG; 5948c2ecf20Sopenharmony_ci else if (S_ISLNK(le16_to_cpu( 5958c2ecf20Sopenharmony_ci dentry_group->nsl[j].i_mode))) 5968c2ecf20Sopenharmony_ci file_type = DT_LNK; 5978c2ecf20Sopenharmony_ci else 5988c2ecf20Sopenharmony_ci continue; 5998c2ecf20Sopenharmony_ci 6008c2ecf20Sopenharmony_ci pos = hmdfs_set_pos(0, i, j); 6018c2ecf20Sopenharmony_ci is_continue = dir_emit( 6028c2ecf20Sopenharmony_ci ctx, dentry_group->filename[j], len, 6038c2ecf20Sopenharmony_ci le64_to_cpu(dentry_group->nsl[j].i_ino), 6048c2ecf20Sopenharmony_ci file_type); 6058c2ecf20Sopenharmony_ci if (!is_continue) { 6068c2ecf20Sopenharmony_ci ctx->pos = pos; 6078c2ecf20Sopenharmony_ci iterate_result = 1; 6088c2ecf20Sopenharmony_ci goto done; 6098c2ecf20Sopenharmony_ci } 6108c2ecf20Sopenharmony_ci } 6118c2ecf20Sopenharmony_ci offset = 0; 6128c2ecf20Sopenharmony_ci } 6138c2ecf20Sopenharmony_ci 6148c2ecf20Sopenharmony_cidone: 6158c2ecf20Sopenharmony_ci hmdfs_revert_fsids(saved_cred); 6168c2ecf20Sopenharmony_ci kfree(dentry_group); 6178c2ecf20Sopenharmony_ci fput(handler); 6188c2ecf20Sopenharmony_ci return iterate_result; 6198c2ecf20Sopenharmony_ci} 6208c2ecf20Sopenharmony_ci 6218c2ecf20Sopenharmony_ciunsigned int get_max_depth(struct file *filp) 6228c2ecf20Sopenharmony_ci{ 6238c2ecf20Sopenharmony_ci size_t isize; 6248c2ecf20Sopenharmony_ci 6258c2ecf20Sopenharmony_ci isize = get_dentry_group_cnt(file_inode(filp)) / BUCKET_BLOCKS; 6268c2ecf20Sopenharmony_ci 6278c2ecf20Sopenharmony_ci return get_count_order(isize + 1); 6288c2ecf20Sopenharmony_ci} 6298c2ecf20Sopenharmony_ci 6308c2ecf20Sopenharmony_cistruct hmdfs_dentry_group *find_dentry_page(struct hmdfs_sb_info *sbi, 6318c2ecf20Sopenharmony_ci pgoff_t index, struct file *filp) 6328c2ecf20Sopenharmony_ci{ 6338c2ecf20Sopenharmony_ci int size; 6348c2ecf20Sopenharmony_ci struct hmdfs_dentry_group *dentry_blk = NULL; 6358c2ecf20Sopenharmony_ci loff_t pos = get_dentry_group_pos(index); 6368c2ecf20Sopenharmony_ci int err; 6378c2ecf20Sopenharmony_ci 6388c2ecf20Sopenharmony_ci dentry_blk = kmalloc(sizeof(*dentry_blk), GFP_KERNEL); 6398c2ecf20Sopenharmony_ci if (!dentry_blk) 6408c2ecf20Sopenharmony_ci return NULL; 6418c2ecf20Sopenharmony_ci 6428c2ecf20Sopenharmony_ci err = hmdfs_wlock_file(filp, pos, DENTRYGROUP_SIZE); 6438c2ecf20Sopenharmony_ci if (err) { 6448c2ecf20Sopenharmony_ci hmdfs_err("lock file pos %lld failed", pos); 6458c2ecf20Sopenharmony_ci kfree(dentry_blk); 6468c2ecf20Sopenharmony_ci return NULL; 6478c2ecf20Sopenharmony_ci } 6488c2ecf20Sopenharmony_ci 6498c2ecf20Sopenharmony_ci size = cache_file_read(sbi, filp, dentry_blk, (size_t)DENTRYGROUP_SIZE, 6508c2ecf20Sopenharmony_ci &pos); 6518c2ecf20Sopenharmony_ci if (size != DENTRYGROUP_SIZE) { 6528c2ecf20Sopenharmony_ci hmdfs_unlock_file(filp, pos, DENTRYGROUP_SIZE); 6538c2ecf20Sopenharmony_ci kfree(dentry_blk); 6548c2ecf20Sopenharmony_ci dentry_blk = NULL; 6558c2ecf20Sopenharmony_ci } 6568c2ecf20Sopenharmony_ci 6578c2ecf20Sopenharmony_ci return dentry_blk; 6588c2ecf20Sopenharmony_ci} 6598c2ecf20Sopenharmony_ci 6608c2ecf20Sopenharmony_cistatic ssize_t write_dentry_page(struct file *filp, const void *buffer, 6618c2ecf20Sopenharmony_ci int buffersize, loff_t position) 6628c2ecf20Sopenharmony_ci{ 6638c2ecf20Sopenharmony_ci ssize_t size; 6648c2ecf20Sopenharmony_ci 6658c2ecf20Sopenharmony_ci size = kernel_write(filp, buffer, (size_t)buffersize, &position); 6668c2ecf20Sopenharmony_ci if (size != buffersize) 6678c2ecf20Sopenharmony_ci hmdfs_err("write failed, ret = %zd", size); 6688c2ecf20Sopenharmony_ci 6698c2ecf20Sopenharmony_ci return size; 6708c2ecf20Sopenharmony_ci} 6718c2ecf20Sopenharmony_ci 6728c2ecf20Sopenharmony_cistatic struct hmdfs_dentry *find_in_block(struct hmdfs_dentry_group *dentry_blk, 6738c2ecf20Sopenharmony_ci __u32 namehash, 6748c2ecf20Sopenharmony_ci const struct qstr *qstr, 6758c2ecf20Sopenharmony_ci struct hmdfs_dentry **insense_de, 6768c2ecf20Sopenharmony_ci bool case_sense) 6778c2ecf20Sopenharmony_ci{ 6788c2ecf20Sopenharmony_ci struct hmdfs_dentry *de; 6798c2ecf20Sopenharmony_ci unsigned long bit_pos = 0; 6808c2ecf20Sopenharmony_ci int max_len = 0; 6818c2ecf20Sopenharmony_ci 6828c2ecf20Sopenharmony_ci while (bit_pos < DENTRY_PER_GROUP) { 6838c2ecf20Sopenharmony_ci if (!test_bit_le(bit_pos, dentry_blk->bitmap)) { 6848c2ecf20Sopenharmony_ci bit_pos++; 6858c2ecf20Sopenharmony_ci max_len++; 6868c2ecf20Sopenharmony_ci continue; 6878c2ecf20Sopenharmony_ci } 6888c2ecf20Sopenharmony_ci de = &dentry_blk->nsl[bit_pos]; 6898c2ecf20Sopenharmony_ci if (unlikely(!de->namelen)) { 6908c2ecf20Sopenharmony_ci bit_pos++; 6918c2ecf20Sopenharmony_ci continue; 6928c2ecf20Sopenharmony_ci } 6938c2ecf20Sopenharmony_ci 6948c2ecf20Sopenharmony_ci if (le32_to_cpu(de->hash) == namehash && 6958c2ecf20Sopenharmony_ci le16_to_cpu(de->namelen) == qstr->len && 6968c2ecf20Sopenharmony_ci !memcmp(qstr->name, dentry_blk->filename[bit_pos], 6978c2ecf20Sopenharmony_ci le16_to_cpu(de->namelen))) 6988c2ecf20Sopenharmony_ci goto found; 6998c2ecf20Sopenharmony_ci if (!(*insense_de) && !case_sense && 7008c2ecf20Sopenharmony_ci le32_to_cpu(de->hash) == namehash && 7018c2ecf20Sopenharmony_ci le16_to_cpu(de->namelen) == qstr->len && 7028c2ecf20Sopenharmony_ci str_n_case_eq(qstr->name, dentry_blk->filename[bit_pos], 7038c2ecf20Sopenharmony_ci le16_to_cpu(de->namelen))) 7048c2ecf20Sopenharmony_ci *insense_de = de; 7058c2ecf20Sopenharmony_ci max_len = 0; 7068c2ecf20Sopenharmony_ci bit_pos += get_dentry_slots(le16_to_cpu(de->namelen)); 7078c2ecf20Sopenharmony_ci } 7088c2ecf20Sopenharmony_ci de = NULL; 7098c2ecf20Sopenharmony_cifound: 7108c2ecf20Sopenharmony_ci return de; 7118c2ecf20Sopenharmony_ci} 7128c2ecf20Sopenharmony_ci 7138c2ecf20Sopenharmony_cistatic struct hmdfs_dentry *hmdfs_in_level(struct dentry *child_dentry, 7148c2ecf20Sopenharmony_ci unsigned int level, 7158c2ecf20Sopenharmony_ci struct hmdfs_dcache_lookup_ctx *ctx) 7168c2ecf20Sopenharmony_ci{ 7178c2ecf20Sopenharmony_ci unsigned long nbucket; 7188c2ecf20Sopenharmony_ci unsigned long bidx, end_block; 7198c2ecf20Sopenharmony_ci struct hmdfs_dentry *de = NULL; 7208c2ecf20Sopenharmony_ci struct hmdfs_dentry *tmp_insense_de = NULL; 7218c2ecf20Sopenharmony_ci struct hmdfs_dentry_group *dentry_blk; 7228c2ecf20Sopenharmony_ci 7238c2ecf20Sopenharmony_ci nbucket = get_bucket_by_level(level); 7248c2ecf20Sopenharmony_ci if (!nbucket) 7258c2ecf20Sopenharmony_ci return de; 7268c2ecf20Sopenharmony_ci 7278c2ecf20Sopenharmony_ci bidx = get_bucketaddr(level, ctx->hash % nbucket) * BUCKET_BLOCKS; 7288c2ecf20Sopenharmony_ci end_block = bidx + BUCKET_BLOCKS; 7298c2ecf20Sopenharmony_ci 7308c2ecf20Sopenharmony_ci for (; bidx < end_block; bidx++) { 7318c2ecf20Sopenharmony_ci dentry_blk = find_dentry_page(ctx->sbi, bidx, ctx->filp); 7328c2ecf20Sopenharmony_ci if (!dentry_blk) 7338c2ecf20Sopenharmony_ci break; 7348c2ecf20Sopenharmony_ci 7358c2ecf20Sopenharmony_ci de = find_in_block(dentry_blk, ctx->hash, ctx->name, 7368c2ecf20Sopenharmony_ci &tmp_insense_de, ctx->sbi->s_case_sensitive); 7378c2ecf20Sopenharmony_ci if (!de && !(ctx->insense_de) && tmp_insense_de) { 7388c2ecf20Sopenharmony_ci ctx->insense_de = tmp_insense_de; 7398c2ecf20Sopenharmony_ci ctx->insense_page = dentry_blk; 7408c2ecf20Sopenharmony_ci ctx->insense_bidx = bidx; 7418c2ecf20Sopenharmony_ci } else if (!de) { 7428c2ecf20Sopenharmony_ci hmdfs_unlock_file(ctx->filp, get_dentry_group_pos(bidx), 7438c2ecf20Sopenharmony_ci DENTRYGROUP_SIZE); 7448c2ecf20Sopenharmony_ci kfree(dentry_blk); 7458c2ecf20Sopenharmony_ci } else { 7468c2ecf20Sopenharmony_ci ctx->page = dentry_blk; 7478c2ecf20Sopenharmony_ci break; 7488c2ecf20Sopenharmony_ci } 7498c2ecf20Sopenharmony_ci } 7508c2ecf20Sopenharmony_ci ctx->bidx = bidx; 7518c2ecf20Sopenharmony_ci return de; 7528c2ecf20Sopenharmony_ci} 7538c2ecf20Sopenharmony_ci 7548c2ecf20Sopenharmony_cistruct hmdfs_dentry *hmdfs_find_dentry(struct dentry *child_dentry, 7558c2ecf20Sopenharmony_ci struct hmdfs_dcache_lookup_ctx *ctx) 7568c2ecf20Sopenharmony_ci{ 7578c2ecf20Sopenharmony_ci struct hmdfs_dentry *de = NULL; 7588c2ecf20Sopenharmony_ci unsigned int max_depth; 7598c2ecf20Sopenharmony_ci unsigned int level; 7608c2ecf20Sopenharmony_ci 7618c2ecf20Sopenharmony_ci if (!ctx->filp) 7628c2ecf20Sopenharmony_ci return NULL; 7638c2ecf20Sopenharmony_ci 7648c2ecf20Sopenharmony_ci ctx->hash = hmdfs_dentry_hash(ctx->name, ctx->sbi->s_case_sensitive); 7658c2ecf20Sopenharmony_ci 7668c2ecf20Sopenharmony_ci max_depth = get_max_depth(ctx->filp); 7678c2ecf20Sopenharmony_ci for (level = 0; level < max_depth; level++) { 7688c2ecf20Sopenharmony_ci de = hmdfs_in_level(child_dentry, level, ctx); 7698c2ecf20Sopenharmony_ci if (de) { 7708c2ecf20Sopenharmony_ci if (ctx->insense_page) { 7718c2ecf20Sopenharmony_ci hmdfs_unlock_file(ctx->filp, 7728c2ecf20Sopenharmony_ci get_dentry_group_pos(ctx->insense_bidx), 7738c2ecf20Sopenharmony_ci DENTRYGROUP_SIZE); 7748c2ecf20Sopenharmony_ci kfree(ctx->insense_page); 7758c2ecf20Sopenharmony_ci ctx->insense_page = NULL; 7768c2ecf20Sopenharmony_ci } 7778c2ecf20Sopenharmony_ci return de; 7788c2ecf20Sopenharmony_ci } 7798c2ecf20Sopenharmony_ci } 7808c2ecf20Sopenharmony_ci if (ctx->insense_de) { 7818c2ecf20Sopenharmony_ci ctx->bidx = ctx->insense_bidx; 7828c2ecf20Sopenharmony_ci ctx->page = ctx->insense_page; 7838c2ecf20Sopenharmony_ci ctx->insense_bidx = 0; 7848c2ecf20Sopenharmony_ci ctx->insense_page = NULL; 7858c2ecf20Sopenharmony_ci } 7868c2ecf20Sopenharmony_ci return ctx->insense_de; 7878c2ecf20Sopenharmony_ci} 7888c2ecf20Sopenharmony_ci 7898c2ecf20Sopenharmony_civoid update_dentry(struct hmdfs_dentry_group *d, struct dentry *child_dentry, 7908c2ecf20Sopenharmony_ci struct inode *inode, struct super_block *hmdfs_sb, 7918c2ecf20Sopenharmony_ci __u32 name_hash, unsigned int bit_pos) 7928c2ecf20Sopenharmony_ci{ 7938c2ecf20Sopenharmony_ci struct hmdfs_dentry *de; 7948c2ecf20Sopenharmony_ci struct hmdfs_dentry_info *gdi; 7958c2ecf20Sopenharmony_ci const struct qstr name = child_dentry->d_name; 7968c2ecf20Sopenharmony_ci int slots = get_dentry_slots(name.len); 7978c2ecf20Sopenharmony_ci int i; 7988c2ecf20Sopenharmony_ci unsigned long ino; 7998c2ecf20Sopenharmony_ci __u32 igen; 8008c2ecf20Sopenharmony_ci 8018c2ecf20Sopenharmony_ci gdi = hmdfs_sb == child_dentry->d_sb ? hmdfs_d(child_dentry) : NULL; 8028c2ecf20Sopenharmony_ci if (!gdi && S_ISLNK(d_inode(child_dentry)->i_mode)) { 8038c2ecf20Sopenharmony_ci ino = d_inode(child_dentry)->i_ino; 8048c2ecf20Sopenharmony_ci igen = d_inode(child_dentry)->i_generation; 8058c2ecf20Sopenharmony_ci } else { 8068c2ecf20Sopenharmony_ci ino = inode->i_ino; 8078c2ecf20Sopenharmony_ci igen = inode->i_generation; 8088c2ecf20Sopenharmony_ci } 8098c2ecf20Sopenharmony_ci 8108c2ecf20Sopenharmony_ci de = &d->nsl[bit_pos]; 8118c2ecf20Sopenharmony_ci de->hash = cpu_to_le32(name_hash); 8128c2ecf20Sopenharmony_ci de->namelen = cpu_to_le16(name.len); 8138c2ecf20Sopenharmony_ci memcpy(d->filename[bit_pos], name.name, name.len); 8148c2ecf20Sopenharmony_ci de->i_mtime = cpu_to_le64(inode->i_mtime.tv_sec); 8158c2ecf20Sopenharmony_ci de->i_mtime_nsec = cpu_to_le32(inode->i_mtime.tv_nsec); 8168c2ecf20Sopenharmony_ci de->i_size = cpu_to_le64(inode->i_size); 8178c2ecf20Sopenharmony_ci de->i_ino = cpu_to_le64(generate_u64_ino(ino, igen)); 8188c2ecf20Sopenharmony_ci de->i_flag = 0; 8198c2ecf20Sopenharmony_ci if (gdi && hm_islnk(gdi->file_type)) 8208c2ecf20Sopenharmony_ci de->i_mode = cpu_to_le16(S_IFLNK); 8218c2ecf20Sopenharmony_ci else if (!gdi && S_ISLNK(d_inode(child_dentry)->i_mode)) 8228c2ecf20Sopenharmony_ci de->i_mode = d_inode(child_dentry)->i_mode; 8238c2ecf20Sopenharmony_ci else 8248c2ecf20Sopenharmony_ci de->i_mode = cpu_to_le16(inode->i_mode); 8258c2ecf20Sopenharmony_ci 8268c2ecf20Sopenharmony_ci for (i = 0; i < slots; i++) { 8278c2ecf20Sopenharmony_ci __set_bit_le(bit_pos + i, d->bitmap); 8288c2ecf20Sopenharmony_ci /* avoid wrong garbage data for readdir */ 8298c2ecf20Sopenharmony_ci if (i) 8308c2ecf20Sopenharmony_ci (de + i)->namelen = 0; 8318c2ecf20Sopenharmony_ci } 8328c2ecf20Sopenharmony_ci} 8338c2ecf20Sopenharmony_ci 8348c2ecf20Sopenharmony_ciint room_for_filename(const void *bitmap, int slots, int max_slots) 8358c2ecf20Sopenharmony_ci{ 8368c2ecf20Sopenharmony_ci int bit_start = 0; 8378c2ecf20Sopenharmony_ci int zero_start, zero_end; 8388c2ecf20Sopenharmony_cinext: 8398c2ecf20Sopenharmony_ci zero_start = find_next_zero_bit_le(bitmap, max_slots, bit_start); 8408c2ecf20Sopenharmony_ci if (zero_start >= max_slots) 8418c2ecf20Sopenharmony_ci return max_slots; 8428c2ecf20Sopenharmony_ci 8438c2ecf20Sopenharmony_ci zero_end = find_next_bit_le(bitmap, max_slots, zero_start); 8448c2ecf20Sopenharmony_ci if (zero_end - zero_start >= slots) 8458c2ecf20Sopenharmony_ci return zero_start; 8468c2ecf20Sopenharmony_ci 8478c2ecf20Sopenharmony_ci bit_start = zero_end + 1; 8488c2ecf20Sopenharmony_ci 8498c2ecf20Sopenharmony_ci if (zero_end + 1 >= max_slots) 8508c2ecf20Sopenharmony_ci return max_slots; 8518c2ecf20Sopenharmony_ci goto next; 8528c2ecf20Sopenharmony_ci} 8538c2ecf20Sopenharmony_ci 8548c2ecf20Sopenharmony_civoid create_in_cache_file(uint64_t dev_id, struct dentry *dentry) 8558c2ecf20Sopenharmony_ci{ 8568c2ecf20Sopenharmony_ci struct clearcache_item *item = NULL; 8578c2ecf20Sopenharmony_ci 8588c2ecf20Sopenharmony_ci item = hmdfs_find_cache_item(dev_id, dentry->d_parent); 8598c2ecf20Sopenharmony_ci if (item) { 8608c2ecf20Sopenharmony_ci if (d_inode(dentry)) 8618c2ecf20Sopenharmony_ci create_dentry(dentry, d_inode(dentry), item->filp, 8628c2ecf20Sopenharmony_ci hmdfs_sb(dentry->d_sb)); 8638c2ecf20Sopenharmony_ci else 8648c2ecf20Sopenharmony_ci hmdfs_err("inode is null!"); 8658c2ecf20Sopenharmony_ci kref_put(&item->ref, release_cache_item); 8668c2ecf20Sopenharmony_ci } else { 8678c2ecf20Sopenharmony_ci hmdfs_info("find cache item failed, device_id:%llu", dev_id); 8688c2ecf20Sopenharmony_ci } 8698c2ecf20Sopenharmony_ci} 8708c2ecf20Sopenharmony_ci 8718c2ecf20Sopenharmony_ciint create_dentry(struct dentry *child_dentry, struct inode *inode, 8728c2ecf20Sopenharmony_ci struct file *file, struct hmdfs_sb_info *sbi) 8738c2ecf20Sopenharmony_ci{ 8748c2ecf20Sopenharmony_ci unsigned int bit_pos, level; 8758c2ecf20Sopenharmony_ci unsigned long bidx, end_block; 8768c2ecf20Sopenharmony_ci const struct qstr qstr = child_dentry->d_name; 8778c2ecf20Sopenharmony_ci __u32 namehash; 8788c2ecf20Sopenharmony_ci loff_t pos; 8798c2ecf20Sopenharmony_ci ssize_t size; 8808c2ecf20Sopenharmony_ci int ret = 0; 8818c2ecf20Sopenharmony_ci struct hmdfs_dentry_group *dentry_blk = NULL; 8828c2ecf20Sopenharmony_ci 8838c2ecf20Sopenharmony_ci level = 0; 8848c2ecf20Sopenharmony_ci 8858c2ecf20Sopenharmony_ci namehash = hmdfs_dentry_hash(&qstr, sbi->s_case_sensitive); 8868c2ecf20Sopenharmony_ci 8878c2ecf20Sopenharmony_ci dentry_blk = kmalloc(sizeof(*dentry_blk), GFP_KERNEL); 8888c2ecf20Sopenharmony_ci if (!dentry_blk) { 8898c2ecf20Sopenharmony_ci ret = -ENOMEM; 8908c2ecf20Sopenharmony_ci goto out_err; 8918c2ecf20Sopenharmony_ci } 8928c2ecf20Sopenharmony_cifind: 8938c2ecf20Sopenharmony_ci if (level == MAX_BUCKET_LEVEL) { 8948c2ecf20Sopenharmony_ci ret = -ENOSPC; 8958c2ecf20Sopenharmony_ci goto out; 8968c2ecf20Sopenharmony_ci } 8978c2ecf20Sopenharmony_ci bidx = BUCKET_BLOCKS * 8988c2ecf20Sopenharmony_ci get_bucketaddr(level, namehash % get_bucket_by_level(level)); 8998c2ecf20Sopenharmony_ci end_block = bidx + BUCKET_BLOCKS; 9008c2ecf20Sopenharmony_ci if (end_block > get_dentry_group_cnt(file_inode(file))) { 9018c2ecf20Sopenharmony_ci if (cache_file_truncate(sbi, &(file->f_path), 9028c2ecf20Sopenharmony_ci get_dcache_file_size(level))) { 9038c2ecf20Sopenharmony_ci ret = -ENOSPC; 9048c2ecf20Sopenharmony_ci goto out; 9058c2ecf20Sopenharmony_ci } 9068c2ecf20Sopenharmony_ci } 9078c2ecf20Sopenharmony_ci 9088c2ecf20Sopenharmony_ci for (; bidx < end_block; bidx++) { 9098c2ecf20Sopenharmony_ci int size; 9108c2ecf20Sopenharmony_ci 9118c2ecf20Sopenharmony_ci pos = get_dentry_group_pos(bidx); 9128c2ecf20Sopenharmony_ci ret = hmdfs_wlock_file(file, pos, DENTRYGROUP_SIZE); 9138c2ecf20Sopenharmony_ci if (ret) 9148c2ecf20Sopenharmony_ci goto out; 9158c2ecf20Sopenharmony_ci 9168c2ecf20Sopenharmony_ci size = cache_file_read(sbi, file, dentry_blk, 9178c2ecf20Sopenharmony_ci (size_t)DENTRYGROUP_SIZE, &pos); 9188c2ecf20Sopenharmony_ci if (size != DENTRYGROUP_SIZE) { 9198c2ecf20Sopenharmony_ci ret = -ENOSPC; 9208c2ecf20Sopenharmony_ci hmdfs_unlock_file(file, pos, DENTRYGROUP_SIZE); 9218c2ecf20Sopenharmony_ci goto out; 9228c2ecf20Sopenharmony_ci } 9238c2ecf20Sopenharmony_ci 9248c2ecf20Sopenharmony_ci bit_pos = room_for_filename(&dentry_blk->bitmap, 9258c2ecf20Sopenharmony_ci get_dentry_slots(qstr.len), 9268c2ecf20Sopenharmony_ci DENTRY_PER_GROUP); 9278c2ecf20Sopenharmony_ci if (bit_pos < DENTRY_PER_GROUP) 9288c2ecf20Sopenharmony_ci goto add; 9298c2ecf20Sopenharmony_ci hmdfs_unlock_file(file, pos, DENTRYGROUP_SIZE); 9308c2ecf20Sopenharmony_ci } 9318c2ecf20Sopenharmony_ci ++level; 9328c2ecf20Sopenharmony_ci goto find; 9338c2ecf20Sopenharmony_ciadd: 9348c2ecf20Sopenharmony_ci pos = get_dentry_group_pos(bidx); 9358c2ecf20Sopenharmony_ci update_dentry(dentry_blk, child_dentry, inode, sbi->sb, namehash, 9368c2ecf20Sopenharmony_ci bit_pos); 9378c2ecf20Sopenharmony_ci size = cache_file_write(sbi, file, dentry_blk, 9388c2ecf20Sopenharmony_ci sizeof(struct hmdfs_dentry_group), &pos); 9398c2ecf20Sopenharmony_ci if (size != sizeof(struct hmdfs_dentry_group)) 9408c2ecf20Sopenharmony_ci hmdfs_err("cache file write failed!, ret = %zd", size); 9418c2ecf20Sopenharmony_ci hmdfs_unlock_file(file, pos, DENTRYGROUP_SIZE); 9428c2ecf20Sopenharmony_ciout: 9438c2ecf20Sopenharmony_ci kfree(dentry_blk); 9448c2ecf20Sopenharmony_ciout_err: 9458c2ecf20Sopenharmony_ci return ret; 9468c2ecf20Sopenharmony_ci} 9478c2ecf20Sopenharmony_ci 9488c2ecf20Sopenharmony_civoid hmdfs_init_dcache_lookup_ctx(struct hmdfs_dcache_lookup_ctx *ctx, 9498c2ecf20Sopenharmony_ci struct hmdfs_sb_info *sbi, 9508c2ecf20Sopenharmony_ci const struct qstr *qstr, struct file *filp) 9518c2ecf20Sopenharmony_ci{ 9528c2ecf20Sopenharmony_ci ctx->sbi = sbi; 9538c2ecf20Sopenharmony_ci ctx->name = qstr; 9548c2ecf20Sopenharmony_ci ctx->filp = filp; 9558c2ecf20Sopenharmony_ci ctx->bidx = 0; 9568c2ecf20Sopenharmony_ci ctx->page = NULL; 9578c2ecf20Sopenharmony_ci ctx->insense_de = NULL; 9588c2ecf20Sopenharmony_ci ctx->insense_bidx = 0; 9598c2ecf20Sopenharmony_ci ctx->insense_page = NULL; 9608c2ecf20Sopenharmony_ci} 9618c2ecf20Sopenharmony_ci 9628c2ecf20Sopenharmony_ciint update_inode_to_dentry(struct dentry *child_dentry, struct inode *inode) 9638c2ecf20Sopenharmony_ci{ 9648c2ecf20Sopenharmony_ci struct hmdfs_sb_info *sbi = d_inode(child_dentry)->i_sb->s_fs_info; 9658c2ecf20Sopenharmony_ci struct hmdfs_dentry *de = NULL; 9668c2ecf20Sopenharmony_ci loff_t ipos; 9678c2ecf20Sopenharmony_ci struct dentry *parent_dentry; 9688c2ecf20Sopenharmony_ci struct cache_file_node *cfn = NULL; 9698c2ecf20Sopenharmony_ci char *relative_path = NULL; 9708c2ecf20Sopenharmony_ci struct hmdfs_dcache_lookup_ctx ctx; 9718c2ecf20Sopenharmony_ci 9728c2ecf20Sopenharmony_ci parent_dentry = child_dentry->d_parent; 9738c2ecf20Sopenharmony_ci if (hmdfs_d(parent_dentry)->dentry_type == HMDFS_LAYER_FIRST_DEVICE) 9748c2ecf20Sopenharmony_ci return 0; 9758c2ecf20Sopenharmony_ci 9768c2ecf20Sopenharmony_ci relative_path = hmdfs_get_dentry_relative_path(parent_dentry); 9778c2ecf20Sopenharmony_ci if (!relative_path) 9788c2ecf20Sopenharmony_ci return -ENOMEM; 9798c2ecf20Sopenharmony_ci 9808c2ecf20Sopenharmony_ci cfn = find_cfn(sbi, HMDFS_SERVER_CID, relative_path, true); 9818c2ecf20Sopenharmony_ci if (!cfn) 9828c2ecf20Sopenharmony_ci goto out; 9838c2ecf20Sopenharmony_ci 9848c2ecf20Sopenharmony_ci hmdfs_init_dcache_lookup_ctx(&ctx, sbi, &child_dentry->d_name, 9858c2ecf20Sopenharmony_ci cfn->filp); 9868c2ecf20Sopenharmony_ci de = hmdfs_find_dentry(child_dentry, &ctx); 9878c2ecf20Sopenharmony_ci if (!de) 9888c2ecf20Sopenharmony_ci goto out_cfn; 9898c2ecf20Sopenharmony_ci 9908c2ecf20Sopenharmony_ci de->i_mtime = cpu_to_le64(inode->i_mtime.tv_sec); 9918c2ecf20Sopenharmony_ci de->i_mtime_nsec = cpu_to_le32(inode->i_mtime.tv_nsec); 9928c2ecf20Sopenharmony_ci de->i_size = cpu_to_le64(inode->i_size); 9938c2ecf20Sopenharmony_ci de->i_ino = cpu_to_le64( 9948c2ecf20Sopenharmony_ci generate_u64_ino(inode->i_ino, inode->i_generation)); 9958c2ecf20Sopenharmony_ci de->i_flag = 0; 9968c2ecf20Sopenharmony_ci 9978c2ecf20Sopenharmony_ci ipos = get_dentry_group_pos(ctx.bidx); 9988c2ecf20Sopenharmony_ci write_dentry_page(cfn->filp, ctx.page, 9998c2ecf20Sopenharmony_ci sizeof(struct hmdfs_dentry_group), ipos); 10008c2ecf20Sopenharmony_ci hmdfs_unlock_file(cfn->filp, ipos, DENTRYGROUP_SIZE); 10018c2ecf20Sopenharmony_ci kfree(ctx.page); 10028c2ecf20Sopenharmony_ciout_cfn: 10038c2ecf20Sopenharmony_ci release_cfn(cfn); 10048c2ecf20Sopenharmony_ciout: 10058c2ecf20Sopenharmony_ci kfree(relative_path); 10068c2ecf20Sopenharmony_ci return 0; 10078c2ecf20Sopenharmony_ci} 10088c2ecf20Sopenharmony_ci 10098c2ecf20Sopenharmony_civoid hmdfs_delete_dentry(struct dentry *d, struct file *filp) 10108c2ecf20Sopenharmony_ci{ 10118c2ecf20Sopenharmony_ci struct hmdfs_dentry *de = NULL; 10128c2ecf20Sopenharmony_ci unsigned int bit_pos; 10138c2ecf20Sopenharmony_ci int slots, i; 10148c2ecf20Sopenharmony_ci loff_t ipos; 10158c2ecf20Sopenharmony_ci ssize_t size; 10168c2ecf20Sopenharmony_ci struct hmdfs_dcache_lookup_ctx ctx; 10178c2ecf20Sopenharmony_ci 10188c2ecf20Sopenharmony_ci hmdfs_init_dcache_lookup_ctx(&ctx, hmdfs_sb(d->d_sb), &d->d_name, filp); 10198c2ecf20Sopenharmony_ci 10208c2ecf20Sopenharmony_ci de = hmdfs_find_dentry(d, &ctx); 10218c2ecf20Sopenharmony_ci if (IS_ERR_OR_NULL(de)) { 10228c2ecf20Sopenharmony_ci hmdfs_info("find dentry failed!, err=%ld", PTR_ERR(de)); 10238c2ecf20Sopenharmony_ci return; 10248c2ecf20Sopenharmony_ci } 10258c2ecf20Sopenharmony_ci slots = get_dentry_slots(le16_to_cpu(de->namelen)); 10268c2ecf20Sopenharmony_ci 10278c2ecf20Sopenharmony_ci bit_pos = de - ctx.page->nsl; 10288c2ecf20Sopenharmony_ci for (i = 0; i < slots; i++) 10298c2ecf20Sopenharmony_ci __clear_bit_le(bit_pos + i, &ctx.page->bitmap); 10308c2ecf20Sopenharmony_ci 10318c2ecf20Sopenharmony_ci ipos = get_dentry_group_pos(ctx.bidx); 10328c2ecf20Sopenharmony_ci size = cache_file_write(hmdfs_sb(d->d_sb), filp, ctx.page, 10338c2ecf20Sopenharmony_ci sizeof(struct hmdfs_dentry_group), &ipos); 10348c2ecf20Sopenharmony_ci if (size != sizeof(struct hmdfs_dentry_group)) 10358c2ecf20Sopenharmony_ci hmdfs_err("cache file write failed!, ret = %zd", size); 10368c2ecf20Sopenharmony_ci hmdfs_unlock_file(filp, ipos, DENTRYGROUP_SIZE); 10378c2ecf20Sopenharmony_ci kfree(ctx.page); 10388c2ecf20Sopenharmony_ci} 10398c2ecf20Sopenharmony_ci 10408c2ecf20Sopenharmony_cistatic int hmdfs_get_cache_path(struct hmdfs_sb_info *sbi, struct path *dir) 10418c2ecf20Sopenharmony_ci{ 10428c2ecf20Sopenharmony_ci struct hmdfs_dentry_info *di = hmdfs_d(sbi->sb->s_root); 10438c2ecf20Sopenharmony_ci int err; 10448c2ecf20Sopenharmony_ci 10458c2ecf20Sopenharmony_ci if (!sbi->s_dentry_cache) { 10468c2ecf20Sopenharmony_ci *dir = di->lower_path; 10478c2ecf20Sopenharmony_ci return 0; 10488c2ecf20Sopenharmony_ci } 10498c2ecf20Sopenharmony_ci 10508c2ecf20Sopenharmony_ci err = kern_path(sbi->cache_dir, LOOKUP_FOLLOW | LOOKUP_DIRECTORY, dir); 10518c2ecf20Sopenharmony_ci if (err) 10528c2ecf20Sopenharmony_ci hmdfs_err("open failed, errno = %d", err); 10538c2ecf20Sopenharmony_ci 10548c2ecf20Sopenharmony_ci return err; 10558c2ecf20Sopenharmony_ci} 10568c2ecf20Sopenharmony_ci 10578c2ecf20Sopenharmony_cistatic void hmdfs_put_cache_path(struct hmdfs_sb_info *sbi, struct path *dir) 10588c2ecf20Sopenharmony_ci{ 10598c2ecf20Sopenharmony_ci if (!sbi->s_dentry_cache) 10608c2ecf20Sopenharmony_ci return; 10618c2ecf20Sopenharmony_ci path_put(dir); 10628c2ecf20Sopenharmony_ci} 10638c2ecf20Sopenharmony_ci 10648c2ecf20Sopenharmony_cistruct file *create_local_dentry_file_cache(struct hmdfs_sb_info *sbi) 10658c2ecf20Sopenharmony_ci{ 10668c2ecf20Sopenharmony_ci struct file *filp = NULL; 10678c2ecf20Sopenharmony_ci const struct cred *old_cred = hmdfs_override_creds(sbi->system_cred); 10688c2ecf20Sopenharmony_ci struct path cache_dir; 10698c2ecf20Sopenharmony_ci int err; 10708c2ecf20Sopenharmony_ci 10718c2ecf20Sopenharmony_ci err = hmdfs_get_cache_path(sbi, &cache_dir); 10728c2ecf20Sopenharmony_ci if (err) { 10738c2ecf20Sopenharmony_ci filp = ERR_PTR(err); 10748c2ecf20Sopenharmony_ci goto out; 10758c2ecf20Sopenharmony_ci } 10768c2ecf20Sopenharmony_ci 10778c2ecf20Sopenharmony_ci filp = file_open_root(&cache_dir, ".", 10788c2ecf20Sopenharmony_ci O_RDWR | O_LARGEFILE | O_TMPFILE, 10798c2ecf20Sopenharmony_ci DENTRY_FILE_PERM); 10808c2ecf20Sopenharmony_ci if (IS_ERR(filp)) 10818c2ecf20Sopenharmony_ci hmdfs_err("dentryfile open failed and exit err=%ld", 10828c2ecf20Sopenharmony_ci PTR_ERR(filp)); 10838c2ecf20Sopenharmony_ci 10848c2ecf20Sopenharmony_ci hmdfs_put_cache_path(sbi, &cache_dir); 10858c2ecf20Sopenharmony_ciout: 10868c2ecf20Sopenharmony_ci hmdfs_revert_creds(old_cred); 10878c2ecf20Sopenharmony_ci return filp; 10888c2ecf20Sopenharmony_ci} 10898c2ecf20Sopenharmony_ci 10908c2ecf20Sopenharmony_cistatic int hmdfs_linkat(struct path *old_path, const char *newname) 10918c2ecf20Sopenharmony_ci{ 10928c2ecf20Sopenharmony_ci struct dentry *new_dentry = NULL; 10938c2ecf20Sopenharmony_ci struct path new_path; 10948c2ecf20Sopenharmony_ci int error; 10958c2ecf20Sopenharmony_ci 10968c2ecf20Sopenharmony_ci new_dentry = kern_path_create(AT_FDCWD, newname, &new_path, 0); 10978c2ecf20Sopenharmony_ci if (IS_ERR(new_dentry)) { 10988c2ecf20Sopenharmony_ci hmdfs_err("create kernel path failed, error: %ld", 10998c2ecf20Sopenharmony_ci PTR_ERR(new_dentry)); 11008c2ecf20Sopenharmony_ci return PTR_ERR(new_dentry); 11018c2ecf20Sopenharmony_ci } 11028c2ecf20Sopenharmony_ci 11038c2ecf20Sopenharmony_ci error = -EXDEV; 11048c2ecf20Sopenharmony_ci if (old_path->mnt != new_path.mnt) 11058c2ecf20Sopenharmony_ci goto out_dput; 11068c2ecf20Sopenharmony_ci 11078c2ecf20Sopenharmony_ci error = vfs_link(old_path->dentry, new_path.dentry->d_inode, new_dentry, 11088c2ecf20Sopenharmony_ci NULL); 11098c2ecf20Sopenharmony_ci 11108c2ecf20Sopenharmony_ciout_dput: 11118c2ecf20Sopenharmony_ci done_path_create(&new_path, new_dentry); 11128c2ecf20Sopenharmony_ci return error; 11138c2ecf20Sopenharmony_ci} 11148c2ecf20Sopenharmony_ci 11158c2ecf20Sopenharmony_cistatic int cache_file_mkdir(const char *name, umode_t mode) 11168c2ecf20Sopenharmony_ci{ 11178c2ecf20Sopenharmony_ci struct dentry *dentry; 11188c2ecf20Sopenharmony_ci struct path path; 11198c2ecf20Sopenharmony_ci int err; 11208c2ecf20Sopenharmony_ci 11218c2ecf20Sopenharmony_ci dentry = kern_path_create(AT_FDCWD, name, &path, LOOKUP_DIRECTORY); 11228c2ecf20Sopenharmony_ci if (IS_ERR(dentry)) 11238c2ecf20Sopenharmony_ci return PTR_ERR(dentry); 11248c2ecf20Sopenharmony_ci 11258c2ecf20Sopenharmony_ci err = vfs_mkdir(d_inode(path.dentry), dentry, mode); 11268c2ecf20Sopenharmony_ci if (err && err != -EEXIST) 11278c2ecf20Sopenharmony_ci hmdfs_err("vfs_mkdir failed, err = %d", err); 11288c2ecf20Sopenharmony_ci 11298c2ecf20Sopenharmony_ci done_path_create(&path, dentry); 11308c2ecf20Sopenharmony_ci return err; 11318c2ecf20Sopenharmony_ci} 11328c2ecf20Sopenharmony_ci 11338c2ecf20Sopenharmony_cistatic int cache_file_create_path(const char *fullpath) 11348c2ecf20Sopenharmony_ci{ 11358c2ecf20Sopenharmony_ci char *path; 11368c2ecf20Sopenharmony_ci char *s; 11378c2ecf20Sopenharmony_ci int err = 0; 11388c2ecf20Sopenharmony_ci 11398c2ecf20Sopenharmony_ci path = kstrdup(fullpath, GFP_KERNEL); 11408c2ecf20Sopenharmony_ci if (!path) 11418c2ecf20Sopenharmony_ci return -ENOMEM; 11428c2ecf20Sopenharmony_ci 11438c2ecf20Sopenharmony_ci s = path + 1; 11448c2ecf20Sopenharmony_ci while (true) { 11458c2ecf20Sopenharmony_ci s = strchr(s, '/'); 11468c2ecf20Sopenharmony_ci if (!s) 11478c2ecf20Sopenharmony_ci break; 11488c2ecf20Sopenharmony_ci s[0] = '\0'; 11498c2ecf20Sopenharmony_ci err = cache_file_mkdir(path, 0755); 11508c2ecf20Sopenharmony_ci if (err && err != -EEXIST) 11518c2ecf20Sopenharmony_ci break; 11528c2ecf20Sopenharmony_ci s[0] = '/'; 11538c2ecf20Sopenharmony_ci s++; 11548c2ecf20Sopenharmony_ci } 11558c2ecf20Sopenharmony_ci kfree(path); 11568c2ecf20Sopenharmony_ci return err; 11578c2ecf20Sopenharmony_ci} 11588c2ecf20Sopenharmony_ci 11598c2ecf20Sopenharmony_cistatic void hmdfs_cache_path_create(char *s, const char *dir, bool server) 11608c2ecf20Sopenharmony_ci{ 11618c2ecf20Sopenharmony_ci if (server) 11628c2ecf20Sopenharmony_ci snprintf(s, PATH_MAX, "%s/dentry_cache/server/", dir); 11638c2ecf20Sopenharmony_ci else 11648c2ecf20Sopenharmony_ci snprintf(s, PATH_MAX, "%s/dentry_cache/client/", dir); 11658c2ecf20Sopenharmony_ci} 11668c2ecf20Sopenharmony_ci 11678c2ecf20Sopenharmony_cistatic void concat_cachefile_name(char *s, uint64_t hash, const char *id, 11688c2ecf20Sopenharmony_ci bool server) 11698c2ecf20Sopenharmony_ci{ 11708c2ecf20Sopenharmony_ci int offset = strlen(s); 11718c2ecf20Sopenharmony_ci 11728c2ecf20Sopenharmony_ci if (server) 11738c2ecf20Sopenharmony_ci snprintf(s + offset, PATH_MAX - offset, "%016llx", hash); 11748c2ecf20Sopenharmony_ci else 11758c2ecf20Sopenharmony_ci snprintf(s + offset, PATH_MAX - offset, "%s_%016llx", id, hash); 11768c2ecf20Sopenharmony_ci} 11778c2ecf20Sopenharmony_ci 11788c2ecf20Sopenharmony_ciint cache_file_name_generate(char *fullname, struct hmdfs_peer *con, 11798c2ecf20Sopenharmony_ci const char *relative_path, bool server) 11808c2ecf20Sopenharmony_ci{ 11818c2ecf20Sopenharmony_ci struct hmdfs_sb_info *sbi = con->sbi; 11828c2ecf20Sopenharmony_ci uint64_t hash; 11838c2ecf20Sopenharmony_ci char cid[HMDFS_CFN_CID_SIZE]; 11848c2ecf20Sopenharmony_ci int err; 11858c2ecf20Sopenharmony_ci 11868c2ecf20Sopenharmony_ci hmdfs_cache_path_create(fullname, sbi->cache_dir, server); 11878c2ecf20Sopenharmony_ci 11888c2ecf20Sopenharmony_ci err = cache_file_create_path(fullname); 11898c2ecf20Sopenharmony_ci if (err && err != -EEXIST) { 11908c2ecf20Sopenharmony_ci hmdfs_err("making dir failed %d", err); 11918c2ecf20Sopenharmony_ci return err; 11928c2ecf20Sopenharmony_ci } 11938c2ecf20Sopenharmony_ci 11948c2ecf20Sopenharmony_ci strncpy(cid, con->cid, HMDFS_CFN_CID_SIZE - 1); 11958c2ecf20Sopenharmony_ci cid[HMDFS_CFN_CID_SIZE - 1] = '\0'; 11968c2ecf20Sopenharmony_ci 11978c2ecf20Sopenharmony_ci hash = path_hash(relative_path, strlen(relative_path), 11988c2ecf20Sopenharmony_ci sbi->s_case_sensitive); 11998c2ecf20Sopenharmony_ci concat_cachefile_name(fullname, hash, cid, server); 12008c2ecf20Sopenharmony_ci 12018c2ecf20Sopenharmony_ci return 0; 12028c2ecf20Sopenharmony_ci} 12038c2ecf20Sopenharmony_ci 12048c2ecf20Sopenharmony_cistatic void free_cfn(struct cache_file_node *cfn) 12058c2ecf20Sopenharmony_ci{ 12068c2ecf20Sopenharmony_ci if (!IS_ERR_OR_NULL(cfn->filp)) 12078c2ecf20Sopenharmony_ci filp_close(cfn->filp, NULL); 12088c2ecf20Sopenharmony_ci 12098c2ecf20Sopenharmony_ci kfree(cfn->relative_path); 12108c2ecf20Sopenharmony_ci kfree(cfn); 12118c2ecf20Sopenharmony_ci} 12128c2ecf20Sopenharmony_ci 12138c2ecf20Sopenharmony_cistatic bool path_cmp(const char *path1, const char *path2, bool case_sensitive) 12148c2ecf20Sopenharmony_ci{ 12158c2ecf20Sopenharmony_ci int ret; 12168c2ecf20Sopenharmony_ci 12178c2ecf20Sopenharmony_ci if (case_sensitive) 12188c2ecf20Sopenharmony_ci ret = strcmp(path1, path2); 12198c2ecf20Sopenharmony_ci else 12208c2ecf20Sopenharmony_ci ret = strcasecmp(path1, path2); 12218c2ecf20Sopenharmony_ci 12228c2ecf20Sopenharmony_ci return !ret; 12238c2ecf20Sopenharmony_ci} 12248c2ecf20Sopenharmony_ci 12258c2ecf20Sopenharmony_cistatic bool dentry_file_match(struct cache_file_node *cfn, const char *id, 12268c2ecf20Sopenharmony_ci const char *path) 12278c2ecf20Sopenharmony_ci{ 12288c2ecf20Sopenharmony_ci return (path_cmp(cfn->relative_path, path, cfn->sbi->s_case_sensitive) && 12298c2ecf20Sopenharmony_ci !strncmp((cfn)->cid, id, HMDFS_CFN_CID_SIZE - 1)); 12308c2ecf20Sopenharmony_ci} 12318c2ecf20Sopenharmony_ci 12328c2ecf20Sopenharmony_cistruct cache_file_node *__find_cfn(struct hmdfs_sb_info *sbi, const char *cid, 12338c2ecf20Sopenharmony_ci const char *path, bool server) 12348c2ecf20Sopenharmony_ci{ 12358c2ecf20Sopenharmony_ci struct cache_file_node *cfn = NULL; 12368c2ecf20Sopenharmony_ci struct list_head *head = NULL; 12378c2ecf20Sopenharmony_ci 12388c2ecf20Sopenharmony_ci head = get_list_head(sbi, server); 12398c2ecf20Sopenharmony_ci 12408c2ecf20Sopenharmony_ci list_for_each_entry(cfn, head, list) { 12418c2ecf20Sopenharmony_ci if (dentry_file_match(cfn, cid, path)) { 12428c2ecf20Sopenharmony_ci refcount_inc(&cfn->ref); 12438c2ecf20Sopenharmony_ci return cfn; 12448c2ecf20Sopenharmony_ci } 12458c2ecf20Sopenharmony_ci } 12468c2ecf20Sopenharmony_ci return NULL; 12478c2ecf20Sopenharmony_ci} 12488c2ecf20Sopenharmony_ci 12498c2ecf20Sopenharmony_cistruct cache_file_node *create_cfn(struct hmdfs_sb_info *sbi, const char *path, 12508c2ecf20Sopenharmony_ci const char *cid, bool server) 12518c2ecf20Sopenharmony_ci{ 12528c2ecf20Sopenharmony_ci struct cache_file_node *cfn = kzalloc(sizeof(*cfn), GFP_KERNEL); 12538c2ecf20Sopenharmony_ci 12548c2ecf20Sopenharmony_ci if (!cfn) 12558c2ecf20Sopenharmony_ci return NULL; 12568c2ecf20Sopenharmony_ci 12578c2ecf20Sopenharmony_ci cfn->relative_path = kstrdup(path, GFP_KERNEL); 12588c2ecf20Sopenharmony_ci if (!cfn->relative_path) 12598c2ecf20Sopenharmony_ci goto out; 12608c2ecf20Sopenharmony_ci 12618c2ecf20Sopenharmony_ci refcount_set(&cfn->ref, 1); 12628c2ecf20Sopenharmony_ci strncpy(cfn->cid, cid, HMDFS_CFN_CID_SIZE - 1); 12638c2ecf20Sopenharmony_ci cfn->cid[HMDFS_CFN_CID_SIZE - 1] = '\0'; 12648c2ecf20Sopenharmony_ci cfn->sbi = sbi; 12658c2ecf20Sopenharmony_ci cfn->server = server; 12668c2ecf20Sopenharmony_ci return cfn; 12678c2ecf20Sopenharmony_ciout: 12688c2ecf20Sopenharmony_ci free_cfn(cfn); 12698c2ecf20Sopenharmony_ci return NULL; 12708c2ecf20Sopenharmony_ci} 12718c2ecf20Sopenharmony_ci 12728c2ecf20Sopenharmony_cistatic struct file *insert_cfn(struct hmdfs_sb_info *sbi, const char *filename, 12738c2ecf20Sopenharmony_ci const char *path, const char *cid, bool server) 12748c2ecf20Sopenharmony_ci{ 12758c2ecf20Sopenharmony_ci const struct cred *old_cred = NULL; 12768c2ecf20Sopenharmony_ci struct cache_file_node *cfn = NULL; 12778c2ecf20Sopenharmony_ci struct cache_file_node *exist = NULL; 12788c2ecf20Sopenharmony_ci struct list_head *head = NULL; 12798c2ecf20Sopenharmony_ci struct file *filp = NULL; 12808c2ecf20Sopenharmony_ci 12818c2ecf20Sopenharmony_ci cfn = create_cfn(sbi, path, cid, server); 12828c2ecf20Sopenharmony_ci if (!cfn) 12838c2ecf20Sopenharmony_ci return ERR_PTR(-ENOMEM); 12848c2ecf20Sopenharmony_ci 12858c2ecf20Sopenharmony_ci old_cred = hmdfs_override_creds(sbi->system_cred); 12868c2ecf20Sopenharmony_ci filp = filp_open(filename, O_RDWR | O_LARGEFILE, 0); 12878c2ecf20Sopenharmony_ci hmdfs_revert_creds(old_cred); 12888c2ecf20Sopenharmony_ci if (IS_ERR(filp)) { 12898c2ecf20Sopenharmony_ci hmdfs_err("open file failed, err=%ld", PTR_ERR(filp)); 12908c2ecf20Sopenharmony_ci goto out; 12918c2ecf20Sopenharmony_ci } 12928c2ecf20Sopenharmony_ci 12938c2ecf20Sopenharmony_ci head = get_list_head(sbi, server); 12948c2ecf20Sopenharmony_ci 12958c2ecf20Sopenharmony_ci mutex_lock(&sbi->cache_list_lock); 12968c2ecf20Sopenharmony_ci exist = __find_cfn(sbi, cid, path, server); 12978c2ecf20Sopenharmony_ci if (!exist) { 12988c2ecf20Sopenharmony_ci cfn->filp = filp; 12998c2ecf20Sopenharmony_ci list_add_tail(&cfn->list, head); 13008c2ecf20Sopenharmony_ci } else { 13018c2ecf20Sopenharmony_ci mutex_unlock(&sbi->cache_list_lock); 13028c2ecf20Sopenharmony_ci release_cfn(exist); 13038c2ecf20Sopenharmony_ci filp_close(filp, NULL); 13048c2ecf20Sopenharmony_ci filp = ERR_PTR(-EEXIST); 13058c2ecf20Sopenharmony_ci goto out; 13068c2ecf20Sopenharmony_ci } 13078c2ecf20Sopenharmony_ci mutex_unlock(&sbi->cache_list_lock); 13088c2ecf20Sopenharmony_ci return filp; 13098c2ecf20Sopenharmony_ciout: 13108c2ecf20Sopenharmony_ci free_cfn(cfn); 13118c2ecf20Sopenharmony_ci return filp; 13128c2ecf20Sopenharmony_ci} 13138c2ecf20Sopenharmony_ci 13148c2ecf20Sopenharmony_ciint hmdfs_rename_dentry(struct dentry *old_dentry, struct dentry *new_dentry, 13158c2ecf20Sopenharmony_ci struct file *old_filp, struct file *new_filp) 13168c2ecf20Sopenharmony_ci{ 13178c2ecf20Sopenharmony_ci int ret; 13188c2ecf20Sopenharmony_ci struct hmdfs_sb_info *sbi = hmdfs_sb(new_dentry->d_sb); 13198c2ecf20Sopenharmony_ci 13208c2ecf20Sopenharmony_ci /* 13218c2ecf20Sopenharmony_ci * Try to delete first, because stale dentry might exist after 13228c2ecf20Sopenharmony_ci * coverwrite. 13238c2ecf20Sopenharmony_ci */ 13248c2ecf20Sopenharmony_ci hmdfs_delete_dentry(new_dentry, new_filp); 13258c2ecf20Sopenharmony_ci 13268c2ecf20Sopenharmony_ci ret = create_dentry(new_dentry, d_inode(old_dentry), new_filp, sbi); 13278c2ecf20Sopenharmony_ci if (ret) { 13288c2ecf20Sopenharmony_ci hmdfs_err("create dentry failed!, err=%d", ret); 13298c2ecf20Sopenharmony_ci return ret; 13308c2ecf20Sopenharmony_ci } 13318c2ecf20Sopenharmony_ci 13328c2ecf20Sopenharmony_ci hmdfs_delete_dentry(old_dentry, old_filp); 13338c2ecf20Sopenharmony_ci return 0; 13348c2ecf20Sopenharmony_ci} 13358c2ecf20Sopenharmony_ci 13368c2ecf20Sopenharmony_ci/** 13378c2ecf20Sopenharmony_ci * cache_file_persistent - link the tmpfile to the cache dir 13388c2ecf20Sopenharmony_ci * @con: the connection peer 13398c2ecf20Sopenharmony_ci * @filp: the file handler of the tmpfile 13408c2ecf20Sopenharmony_ci * @relative_path: the relative path which the tmpfile belongs 13418c2ecf20Sopenharmony_ci * @server: server or client 13428c2ecf20Sopenharmony_ci * 13438c2ecf20Sopenharmony_ci * Return value: the new file handler of the persistent file if the 13448c2ecf20Sopenharmony_ci * persistent operation succeed. Otherwise will return the original handler 13458c2ecf20Sopenharmony_ci * of the tmpfile passed in, so that the caller does not have to check 13468c2ecf20Sopenharmony_ci * the returned handler. 13478c2ecf20Sopenharmony_ci * 13488c2ecf20Sopenharmony_ci */ 13498c2ecf20Sopenharmony_cistruct file *cache_file_persistent(struct hmdfs_peer *con, struct file *filp, 13508c2ecf20Sopenharmony_ci const char *relative_path, bool server) 13518c2ecf20Sopenharmony_ci{ 13528c2ecf20Sopenharmony_ci struct cache_file_node *cfn = NULL; 13538c2ecf20Sopenharmony_ci char *fullname = NULL; 13548c2ecf20Sopenharmony_ci char *cid = server ? HMDFS_SERVER_CID : (char *)con->cid; 13558c2ecf20Sopenharmony_ci struct file *newf = NULL; 13568c2ecf20Sopenharmony_ci int i = 0; 13578c2ecf20Sopenharmony_ci int len; 13588c2ecf20Sopenharmony_ci int err; 13598c2ecf20Sopenharmony_ci 13608c2ecf20Sopenharmony_ci if (!con->sbi->s_dentry_cache) 13618c2ecf20Sopenharmony_ci return filp; 13628c2ecf20Sopenharmony_ci 13638c2ecf20Sopenharmony_ci cfn = find_cfn(con->sbi, cid, relative_path, server); 13648c2ecf20Sopenharmony_ci if (cfn) { 13658c2ecf20Sopenharmony_ci release_cfn(cfn); 13668c2ecf20Sopenharmony_ci return filp; 13678c2ecf20Sopenharmony_ci } 13688c2ecf20Sopenharmony_ci fullname = kzalloc(PATH_MAX, GFP_KERNEL); 13698c2ecf20Sopenharmony_ci if (!fullname) 13708c2ecf20Sopenharmony_ci return filp; 13718c2ecf20Sopenharmony_ci 13728c2ecf20Sopenharmony_ci err = cache_file_name_generate(fullname, con, relative_path, server); 13738c2ecf20Sopenharmony_ci if (err) 13748c2ecf20Sopenharmony_ci goto out; 13758c2ecf20Sopenharmony_ci 13768c2ecf20Sopenharmony_ci err = __vfs_setxattr(file_dentry(filp), file_inode(filp), 13778c2ecf20Sopenharmony_ci DENTRY_FILE_XATTR_NAME, relative_path, 13788c2ecf20Sopenharmony_ci strlen(relative_path), 0); 13798c2ecf20Sopenharmony_ci if (err) { 13808c2ecf20Sopenharmony_ci hmdfs_err("setxattr for file failed, err=%d", err); 13818c2ecf20Sopenharmony_ci goto out; 13828c2ecf20Sopenharmony_ci } 13838c2ecf20Sopenharmony_ci 13848c2ecf20Sopenharmony_ci len = strlen(fullname); 13858c2ecf20Sopenharmony_ci 13868c2ecf20Sopenharmony_ci do { 13878c2ecf20Sopenharmony_ci err = hmdfs_linkat(&filp->f_path, fullname); 13888c2ecf20Sopenharmony_ci if (!err) 13898c2ecf20Sopenharmony_ci break; 13908c2ecf20Sopenharmony_ci 13918c2ecf20Sopenharmony_ci snprintf(fullname + len, PATH_MAX - len, "_%d", i); 13928c2ecf20Sopenharmony_ci } while (i++ < DENTRY_FILE_NAME_RETRY); 13938c2ecf20Sopenharmony_ci 13948c2ecf20Sopenharmony_ci if (err) { 13958c2ecf20Sopenharmony_ci hmdfs_err("link for file failed, err=%d", err); 13968c2ecf20Sopenharmony_ci goto out; 13978c2ecf20Sopenharmony_ci } 13988c2ecf20Sopenharmony_ci 13998c2ecf20Sopenharmony_ci newf = insert_cfn(con->sbi, fullname, relative_path, cid, server); 14008c2ecf20Sopenharmony_ci if (!IS_ERR(newf)) 14018c2ecf20Sopenharmony_ci filp = newf; 14028c2ecf20Sopenharmony_ciout: 14038c2ecf20Sopenharmony_ci kfree(fullname); 14048c2ecf20Sopenharmony_ci return filp; 14058c2ecf20Sopenharmony_ci} 14068c2ecf20Sopenharmony_ci 14078c2ecf20Sopenharmony_ciint get_cloud_cache_file(struct dentry *dentry, struct hmdfs_sb_info *sbi) 14088c2ecf20Sopenharmony_ci{ 14098c2ecf20Sopenharmony_ci int ret; 14108c2ecf20Sopenharmony_ci ssize_t res; 14118c2ecf20Sopenharmony_ci struct hmdfs_dentry_info *d_info = hmdfs_d(dentry); 14128c2ecf20Sopenharmony_ci struct clearcache_item *item; 14138c2ecf20Sopenharmony_ci struct file *filp = NULL; 14148c2ecf20Sopenharmony_ci uint64_t hash; 14158c2ecf20Sopenharmony_ci char *relative_path = NULL; 14168c2ecf20Sopenharmony_ci char *dirname = NULL; 14178c2ecf20Sopenharmony_ci char *fullname = NULL; 14188c2ecf20Sopenharmony_ci char *cache_file_name = NULL; 14198c2ecf20Sopenharmony_ci char *kvalue = NULL; 14208c2ecf20Sopenharmony_ci 14218c2ecf20Sopenharmony_ci item = hmdfs_find_cache_item(CLOUD_DEVICE, dentry); 14228c2ecf20Sopenharmony_ci if (item) { 14238c2ecf20Sopenharmony_ci kref_put(&item->ref, release_cache_item); 14248c2ecf20Sopenharmony_ci return 0; 14258c2ecf20Sopenharmony_ci } 14268c2ecf20Sopenharmony_ci 14278c2ecf20Sopenharmony_ci relative_path = hmdfs_get_dentry_relative_path(dentry); 14288c2ecf20Sopenharmony_ci if (unlikely(!relative_path)) { 14298c2ecf20Sopenharmony_ci hmdfs_err("get relative path failed %d", -ENOMEM); 14308c2ecf20Sopenharmony_ci ret = -ENOMEM; 14318c2ecf20Sopenharmony_ci goto out; 14328c2ecf20Sopenharmony_ci } 14338c2ecf20Sopenharmony_ci 14348c2ecf20Sopenharmony_ci dirname = kzalloc(PATH_MAX, GFP_KERNEL); 14358c2ecf20Sopenharmony_ci if (!dirname) { 14368c2ecf20Sopenharmony_ci ret = -ENOMEM; 14378c2ecf20Sopenharmony_ci goto out; 14388c2ecf20Sopenharmony_ci } 14398c2ecf20Sopenharmony_ci 14408c2ecf20Sopenharmony_ci cache_file_name = kzalloc(PATH_MAX, GFP_KERNEL); 14418c2ecf20Sopenharmony_ci if (!cache_file_name) { 14428c2ecf20Sopenharmony_ci ret = -ENOMEM; 14438c2ecf20Sopenharmony_ci goto out; 14448c2ecf20Sopenharmony_ci } 14458c2ecf20Sopenharmony_ci 14468c2ecf20Sopenharmony_ci fullname = kzalloc(PATH_MAX, GFP_KERNEL); 14478c2ecf20Sopenharmony_ci if (!fullname) { 14488c2ecf20Sopenharmony_ci ret = -ENOMEM; 14498c2ecf20Sopenharmony_ci goto out; 14508c2ecf20Sopenharmony_ci } 14518c2ecf20Sopenharmony_ci 14528c2ecf20Sopenharmony_ci kvalue = kzalloc(PATH_MAX, GFP_KERNEL); 14538c2ecf20Sopenharmony_ci if (!kvalue) { 14548c2ecf20Sopenharmony_ci ret = -ENOMEM; 14558c2ecf20Sopenharmony_ci goto out; 14568c2ecf20Sopenharmony_ci } 14578c2ecf20Sopenharmony_ci 14588c2ecf20Sopenharmony_ci hash = path_hash(relative_path, strlen(relative_path), 14598c2ecf20Sopenharmony_ci sbi->s_case_sensitive); 14608c2ecf20Sopenharmony_ci concat_cachefile_name(cache_file_name, hash, CLOUD_CID, false); 14618c2ecf20Sopenharmony_ci snprintf(dirname, PATH_MAX, "%s/dentry_cache/cloud/", 14628c2ecf20Sopenharmony_ci sbi->cache_dir); 14638c2ecf20Sopenharmony_ci snprintf(fullname, PATH_MAX, "%s%s", dirname, cache_file_name); 14648c2ecf20Sopenharmony_ci 14658c2ecf20Sopenharmony_ci filp = filp_open(fullname, O_RDWR | O_LARGEFILE, 0); 14668c2ecf20Sopenharmony_ci if (IS_ERR(filp)) { 14678c2ecf20Sopenharmony_ci hmdfs_debug("open fail %ld", PTR_ERR(filp)); 14688c2ecf20Sopenharmony_ci ret = PTR_ERR(filp); 14698c2ecf20Sopenharmony_ci goto out; 14708c2ecf20Sopenharmony_ci } 14718c2ecf20Sopenharmony_ci 14728c2ecf20Sopenharmony_ci res = __vfs_getxattr(file_dentry(filp), file_inode(filp), 14738c2ecf20Sopenharmony_ci DENTRY_FILE_XATTR_NAME, kvalue, PATH_MAX); 14748c2ecf20Sopenharmony_ci if (res <= 0 || res >= PATH_MAX) { 14758c2ecf20Sopenharmony_ci hmdfs_err("getxattr return: %zd", res); 14768c2ecf20Sopenharmony_ci filp_close(filp, NULL); 14778c2ecf20Sopenharmony_ci ret = -ENOENT; 14788c2ecf20Sopenharmony_ci goto out; 14798c2ecf20Sopenharmony_ci } 14808c2ecf20Sopenharmony_ci kvalue[res] = '\0'; 14818c2ecf20Sopenharmony_ci 14828c2ecf20Sopenharmony_ci if (!path_cmp(relative_path, kvalue, sbi->s_case_sensitive)) { 14838c2ecf20Sopenharmony_ci hmdfs_err("relative path from xattr do not match"); 14848c2ecf20Sopenharmony_ci filp_close(filp, NULL); 14858c2ecf20Sopenharmony_ci ret = -ENOENT; 14868c2ecf20Sopenharmony_ci goto out; 14878c2ecf20Sopenharmony_ci } 14888c2ecf20Sopenharmony_ci 14898c2ecf20Sopenharmony_ci mutex_lock(&d_info->cache_pull_lock); 14908c2ecf20Sopenharmony_ci hmdfs_add_cache_list(CLOUD_DEVICE, dentry, filp); 14918c2ecf20Sopenharmony_ci mutex_unlock(&d_info->cache_pull_lock); 14928c2ecf20Sopenharmony_ci 14938c2ecf20Sopenharmony_ci ret = 0; 14948c2ecf20Sopenharmony_ciout: 14958c2ecf20Sopenharmony_ci kfree(relative_path); 14968c2ecf20Sopenharmony_ci kfree(dirname); 14978c2ecf20Sopenharmony_ci kfree(fullname); 14988c2ecf20Sopenharmony_ci kfree(cache_file_name); 14998c2ecf20Sopenharmony_ci kfree(kvalue); 15008c2ecf20Sopenharmony_ci 15018c2ecf20Sopenharmony_ci return ret; 15028c2ecf20Sopenharmony_ci} 15038c2ecf20Sopenharmony_ci 15048c2ecf20Sopenharmony_civoid __destroy_cfn(struct list_head *head) 15058c2ecf20Sopenharmony_ci{ 15068c2ecf20Sopenharmony_ci struct cache_file_node *cfn = NULL; 15078c2ecf20Sopenharmony_ci struct cache_file_node *n = NULL; 15088c2ecf20Sopenharmony_ci 15098c2ecf20Sopenharmony_ci list_for_each_entry_safe(cfn, n, head, list) { 15108c2ecf20Sopenharmony_ci list_del_init(&cfn->list); 15118c2ecf20Sopenharmony_ci release_cfn(cfn); 15128c2ecf20Sopenharmony_ci } 15138c2ecf20Sopenharmony_ci} 15148c2ecf20Sopenharmony_ci 15158c2ecf20Sopenharmony_civoid hmdfs_cfn_destroy(struct hmdfs_sb_info *sbi) 15168c2ecf20Sopenharmony_ci{ 15178c2ecf20Sopenharmony_ci mutex_lock(&sbi->cache_list_lock); 15188c2ecf20Sopenharmony_ci __destroy_cfn(&sbi->client_cache); 15198c2ecf20Sopenharmony_ci __destroy_cfn(&sbi->server_cache); 15208c2ecf20Sopenharmony_ci mutex_unlock(&sbi->cache_list_lock); 15218c2ecf20Sopenharmony_ci} 15228c2ecf20Sopenharmony_ci 15238c2ecf20Sopenharmony_cistruct cache_file_node *find_cfn(struct hmdfs_sb_info *sbi, const char *cid, 15248c2ecf20Sopenharmony_ci const char *path, bool server) 15258c2ecf20Sopenharmony_ci{ 15268c2ecf20Sopenharmony_ci struct cache_file_node *cfn = NULL; 15278c2ecf20Sopenharmony_ci 15288c2ecf20Sopenharmony_ci mutex_lock(&sbi->cache_list_lock); 15298c2ecf20Sopenharmony_ci cfn = __find_cfn(sbi, cid, path, server); 15308c2ecf20Sopenharmony_ci mutex_unlock(&sbi->cache_list_lock); 15318c2ecf20Sopenharmony_ci return cfn; 15328c2ecf20Sopenharmony_ci} 15338c2ecf20Sopenharmony_ci 15348c2ecf20Sopenharmony_civoid release_cfn(struct cache_file_node *cfn) 15358c2ecf20Sopenharmony_ci{ 15368c2ecf20Sopenharmony_ci if (refcount_dec_and_test(&cfn->ref)) 15378c2ecf20Sopenharmony_ci free_cfn(cfn); 15388c2ecf20Sopenharmony_ci} 15398c2ecf20Sopenharmony_ci 15408c2ecf20Sopenharmony_civoid remove_cfn(struct cache_file_node *cfn) 15418c2ecf20Sopenharmony_ci{ 15428c2ecf20Sopenharmony_ci struct hmdfs_sb_info *sbi = cfn->sbi; 15438c2ecf20Sopenharmony_ci bool deleted; 15448c2ecf20Sopenharmony_ci 15458c2ecf20Sopenharmony_ci mutex_lock(&sbi->cache_list_lock); 15468c2ecf20Sopenharmony_ci deleted = list_empty(&cfn->list); 15478c2ecf20Sopenharmony_ci if (!deleted) 15488c2ecf20Sopenharmony_ci list_del_init(&cfn->list); 15498c2ecf20Sopenharmony_ci mutex_unlock(&sbi->cache_list_lock); 15508c2ecf20Sopenharmony_ci if (!deleted) { 15518c2ecf20Sopenharmony_ci delete_dentry_file(cfn->filp); 15528c2ecf20Sopenharmony_ci release_cfn(cfn); 15538c2ecf20Sopenharmony_ci } 15548c2ecf20Sopenharmony_ci} 15558c2ecf20Sopenharmony_ci 15568c2ecf20Sopenharmony_ciint hmdfs_do_lock_file(struct file *filp, unsigned char fl_type, loff_t start, 15578c2ecf20Sopenharmony_ci loff_t len) 15588c2ecf20Sopenharmony_ci{ 15598c2ecf20Sopenharmony_ci struct file_lock fl; 15608c2ecf20Sopenharmony_ci int err; 15618c2ecf20Sopenharmony_ci 15628c2ecf20Sopenharmony_ci locks_init_lock(&fl); 15638c2ecf20Sopenharmony_ci 15648c2ecf20Sopenharmony_ci fl.fl_type = fl_type; 15658c2ecf20Sopenharmony_ci fl.fl_flags = FL_POSIX | FL_CLOSE | FL_SLEEP; 15668c2ecf20Sopenharmony_ci fl.fl_start = start; 15678c2ecf20Sopenharmony_ci fl.fl_end = start + len - 1; 15688c2ecf20Sopenharmony_ci fl.fl_owner = filp; 15698c2ecf20Sopenharmony_ci fl.fl_pid = current->tgid; 15708c2ecf20Sopenharmony_ci fl.fl_file = filp; 15718c2ecf20Sopenharmony_ci fl.fl_ops = NULL; 15728c2ecf20Sopenharmony_ci fl.fl_lmops = NULL; 15738c2ecf20Sopenharmony_ci 15748c2ecf20Sopenharmony_ci err = locks_lock_file_wait(filp, &fl); 15758c2ecf20Sopenharmony_ci if (err) 15768c2ecf20Sopenharmony_ci hmdfs_err("lock file wait failed: %d", err); 15778c2ecf20Sopenharmony_ci 15788c2ecf20Sopenharmony_ci return err; 15798c2ecf20Sopenharmony_ci} 15808c2ecf20Sopenharmony_ci 15818c2ecf20Sopenharmony_ciint hmdfs_wlock_file(struct file *filp, loff_t start, loff_t len) 15828c2ecf20Sopenharmony_ci{ 15838c2ecf20Sopenharmony_ci return hmdfs_do_lock_file(filp, F_WRLCK, start, len); 15848c2ecf20Sopenharmony_ci} 15858c2ecf20Sopenharmony_ci 15868c2ecf20Sopenharmony_ciint hmdfs_rlock_file(struct file *filp, loff_t start, loff_t len) 15878c2ecf20Sopenharmony_ci{ 15888c2ecf20Sopenharmony_ci return hmdfs_do_lock_file(filp, F_RDLCK, start, len); 15898c2ecf20Sopenharmony_ci} 15908c2ecf20Sopenharmony_ci 15918c2ecf20Sopenharmony_ciint hmdfs_unlock_file(struct file *filp, loff_t start, loff_t len) 15928c2ecf20Sopenharmony_ci{ 15938c2ecf20Sopenharmony_ci return hmdfs_do_lock_file(filp, F_UNLCK, start, len); 15948c2ecf20Sopenharmony_ci} 15958c2ecf20Sopenharmony_ci 15968c2ecf20Sopenharmony_cilong cache_file_truncate(struct hmdfs_sb_info *sbi, const struct path *path, 15978c2ecf20Sopenharmony_ci loff_t length) 15988c2ecf20Sopenharmony_ci{ 15998c2ecf20Sopenharmony_ci const struct cred *old_cred = hmdfs_override_creds(sbi->system_cred); 16008c2ecf20Sopenharmony_ci long ret = vfs_truncate(path, length); 16018c2ecf20Sopenharmony_ci 16028c2ecf20Sopenharmony_ci hmdfs_revert_creds(old_cred); 16038c2ecf20Sopenharmony_ci 16048c2ecf20Sopenharmony_ci return ret; 16058c2ecf20Sopenharmony_ci} 16068c2ecf20Sopenharmony_ci 16078c2ecf20Sopenharmony_cissize_t cache_file_read(struct hmdfs_sb_info *sbi, struct file *filp, void *buf, 16088c2ecf20Sopenharmony_ci size_t count, loff_t *pos) 16098c2ecf20Sopenharmony_ci{ 16108c2ecf20Sopenharmony_ci const struct cred *old_cred = hmdfs_override_creds(sbi->system_cred); 16118c2ecf20Sopenharmony_ci ssize_t ret = kernel_read(filp, buf, count, pos); 16128c2ecf20Sopenharmony_ci 16138c2ecf20Sopenharmony_ci hmdfs_revert_creds(old_cred); 16148c2ecf20Sopenharmony_ci 16158c2ecf20Sopenharmony_ci return ret; 16168c2ecf20Sopenharmony_ci} 16178c2ecf20Sopenharmony_ci 16188c2ecf20Sopenharmony_cissize_t cache_file_write(struct hmdfs_sb_info *sbi, struct file *filp, 16198c2ecf20Sopenharmony_ci const void *buf, size_t count, loff_t *pos) 16208c2ecf20Sopenharmony_ci{ 16218c2ecf20Sopenharmony_ci const struct cred *old_cred = hmdfs_override_creds(sbi->system_cred); 16228c2ecf20Sopenharmony_ci ssize_t ret = kernel_write(filp, buf, count, pos); 16238c2ecf20Sopenharmony_ci 16248c2ecf20Sopenharmony_ci hmdfs_revert_creds(old_cred); 16258c2ecf20Sopenharmony_ci 16268c2ecf20Sopenharmony_ci return ret; 16278c2ecf20Sopenharmony_ci} 16288c2ecf20Sopenharmony_ci 16298c2ecf20Sopenharmony_ci 16308c2ecf20Sopenharmony_ciint read_header(struct hmdfs_sb_info *sbi, struct file *filp, 16318c2ecf20Sopenharmony_ci struct hmdfs_dcache_header *header) 16328c2ecf20Sopenharmony_ci{ 16338c2ecf20Sopenharmony_ci ssize_t bytes; 16348c2ecf20Sopenharmony_ci loff_t pos = 0; 16358c2ecf20Sopenharmony_ci 16368c2ecf20Sopenharmony_ci bytes = cache_file_read(sbi, filp, header, sizeof(*header), &pos); 16378c2ecf20Sopenharmony_ci if (bytes != sizeof(*header)) { 16388c2ecf20Sopenharmony_ci hmdfs_err("read file failed, err:%zd", bytes); 16398c2ecf20Sopenharmony_ci return -EIO; 16408c2ecf20Sopenharmony_ci } 16418c2ecf20Sopenharmony_ci 16428c2ecf20Sopenharmony_ci return 0; 16438c2ecf20Sopenharmony_ci} 16448c2ecf20Sopenharmony_ci 16458c2ecf20Sopenharmony_cistatic unsigned long long cache_get_dentry_count(struct hmdfs_sb_info *sbi, 16468c2ecf20Sopenharmony_ci struct file *filp) 16478c2ecf20Sopenharmony_ci{ 16488c2ecf20Sopenharmony_ci struct hmdfs_dcache_header header; 16498c2ecf20Sopenharmony_ci int overallpage; 16508c2ecf20Sopenharmony_ci 16518c2ecf20Sopenharmony_ci overallpage = get_dentry_group_cnt(file_inode(filp)); 16528c2ecf20Sopenharmony_ci if (overallpage == 0) 16538c2ecf20Sopenharmony_ci return 0; 16548c2ecf20Sopenharmony_ci 16558c2ecf20Sopenharmony_ci if (read_header(sbi, filp, &header)) 16568c2ecf20Sopenharmony_ci return 0; 16578c2ecf20Sopenharmony_ci 16588c2ecf20Sopenharmony_ci return le64_to_cpu(header.num); 16598c2ecf20Sopenharmony_ci} 16608c2ecf20Sopenharmony_ci 16618c2ecf20Sopenharmony_cistatic int cache_check_case_sensitive(struct hmdfs_sb_info *sbi, 16628c2ecf20Sopenharmony_ci struct file *filp) 16638c2ecf20Sopenharmony_ci{ 16648c2ecf20Sopenharmony_ci struct hmdfs_dcache_header header; 16658c2ecf20Sopenharmony_ci 16668c2ecf20Sopenharmony_ci if (read_header(sbi, filp, &header)) 16678c2ecf20Sopenharmony_ci return 0; 16688c2ecf20Sopenharmony_ci 16698c2ecf20Sopenharmony_ci if (sbi->s_case_sensitive != (bool)header.case_sensitive) { 16708c2ecf20Sopenharmony_ci hmdfs_info("Case sensitive inconsistent, current fs is: %d, cache is %d, will drop cache", 16718c2ecf20Sopenharmony_ci sbi->s_case_sensitive, header.case_sensitive); 16728c2ecf20Sopenharmony_ci return 0; 16738c2ecf20Sopenharmony_ci } 16748c2ecf20Sopenharmony_ci return 1; 16758c2ecf20Sopenharmony_ci} 16768c2ecf20Sopenharmony_ci 16778c2ecf20Sopenharmony_ciint write_header(struct file *filp, struct hmdfs_dcache_header *header) 16788c2ecf20Sopenharmony_ci{ 16798c2ecf20Sopenharmony_ci loff_t pos = 0; 16808c2ecf20Sopenharmony_ci ssize_t size; 16818c2ecf20Sopenharmony_ci 16828c2ecf20Sopenharmony_ci size = kernel_write(filp, header, sizeof(*header), &pos); 16838c2ecf20Sopenharmony_ci if (size != sizeof(*header)) { 16848c2ecf20Sopenharmony_ci hmdfs_err("update dcache header failed %zd", size); 16858c2ecf20Sopenharmony_ci return -EIO; 16868c2ecf20Sopenharmony_ci } 16878c2ecf20Sopenharmony_ci 16888c2ecf20Sopenharmony_ci return 0; 16898c2ecf20Sopenharmony_ci} 16908c2ecf20Sopenharmony_ci 16918c2ecf20Sopenharmony_civoid add_to_delete_list(struct hmdfs_sb_info *sbi, struct cache_file_node *cfn) 16928c2ecf20Sopenharmony_ci{ 16938c2ecf20Sopenharmony_ci mutex_lock(&sbi->cache_list_lock); 16948c2ecf20Sopenharmony_ci list_add_tail(&cfn->list, &sbi->to_delete); 16958c2ecf20Sopenharmony_ci mutex_unlock(&sbi->cache_list_lock); 16968c2ecf20Sopenharmony_ci} 16978c2ecf20Sopenharmony_ci 16988c2ecf20Sopenharmony_civoid load_cfn(struct hmdfs_sb_info *sbi, const char *fullname, const char *path, 16998c2ecf20Sopenharmony_ci const char *cid, bool server) 17008c2ecf20Sopenharmony_ci{ 17018c2ecf20Sopenharmony_ci struct cache_file_node *cfn = NULL; 17028c2ecf20Sopenharmony_ci struct cache_file_node *cfn1 = NULL; 17038c2ecf20Sopenharmony_ci struct list_head *head = NULL; 17048c2ecf20Sopenharmony_ci 17058c2ecf20Sopenharmony_ci cfn = create_cfn(sbi, path, cid, server); 17068c2ecf20Sopenharmony_ci if (!cfn) 17078c2ecf20Sopenharmony_ci return; 17088c2ecf20Sopenharmony_ci 17098c2ecf20Sopenharmony_ci cfn->filp = filp_open(fullname, O_RDWR | O_LARGEFILE, 0); 17108c2ecf20Sopenharmony_ci if (IS_ERR(cfn->filp)) { 17118c2ecf20Sopenharmony_ci hmdfs_err("open fail %ld", PTR_ERR(cfn->filp)); 17128c2ecf20Sopenharmony_ci goto out; 17138c2ecf20Sopenharmony_ci } 17148c2ecf20Sopenharmony_ci 17158c2ecf20Sopenharmony_ci if (cache_get_dentry_count(sbi, cfn->filp) < sbi->dcache_threshold && strcmp(cid, CLOUD_CID)) { 17168c2ecf20Sopenharmony_ci add_to_delete_list(sbi, cfn); 17178c2ecf20Sopenharmony_ci return; 17188c2ecf20Sopenharmony_ci } 17198c2ecf20Sopenharmony_ci 17208c2ecf20Sopenharmony_ci if (!cache_check_case_sensitive(sbi, cfn->filp) && strcmp(cid, CLOUD_CID)) { 17218c2ecf20Sopenharmony_ci add_to_delete_list(sbi, cfn); 17228c2ecf20Sopenharmony_ci return; 17238c2ecf20Sopenharmony_ci } 17248c2ecf20Sopenharmony_ci 17258c2ecf20Sopenharmony_ci head = get_list_head(sbi, server); 17268c2ecf20Sopenharmony_ci 17278c2ecf20Sopenharmony_ci mutex_lock(&sbi->cache_list_lock); 17288c2ecf20Sopenharmony_ci cfn1 = __find_cfn(sbi, cid, path, server); 17298c2ecf20Sopenharmony_ci if (!cfn1) { 17308c2ecf20Sopenharmony_ci list_add_tail(&cfn->list, head); 17318c2ecf20Sopenharmony_ci } else { 17328c2ecf20Sopenharmony_ci release_cfn(cfn1); 17338c2ecf20Sopenharmony_ci mutex_unlock(&sbi->cache_list_lock); 17348c2ecf20Sopenharmony_ci add_to_delete_list(sbi, cfn); 17358c2ecf20Sopenharmony_ci return; 17368c2ecf20Sopenharmony_ci } 17378c2ecf20Sopenharmony_ci mutex_unlock(&sbi->cache_list_lock); 17388c2ecf20Sopenharmony_ci 17398c2ecf20Sopenharmony_ci return; 17408c2ecf20Sopenharmony_ciout: 17418c2ecf20Sopenharmony_ci free_cfn(cfn); 17428c2ecf20Sopenharmony_ci} 17438c2ecf20Sopenharmony_ci 17448c2ecf20Sopenharmony_cistatic int get_cid_and_hash(const char *name, uint64_t *hash, char *cid) 17458c2ecf20Sopenharmony_ci{ 17468c2ecf20Sopenharmony_ci int len; 17478c2ecf20Sopenharmony_ci char *p = strstr(name, "_"); 17488c2ecf20Sopenharmony_ci 17498c2ecf20Sopenharmony_ci if (!p) 17508c2ecf20Sopenharmony_ci return -EINVAL; 17518c2ecf20Sopenharmony_ci 17528c2ecf20Sopenharmony_ci len = p - name; 17538c2ecf20Sopenharmony_ci if (len >= HMDFS_CFN_CID_SIZE) 17548c2ecf20Sopenharmony_ci return -EINVAL; 17558c2ecf20Sopenharmony_ci 17568c2ecf20Sopenharmony_ci memcpy(cid, name, len); 17578c2ecf20Sopenharmony_ci cid[len] = '\0'; 17588c2ecf20Sopenharmony_ci 17598c2ecf20Sopenharmony_ci if (sscanf(++p, "%llx", hash) != 1) 17608c2ecf20Sopenharmony_ci return -EINVAL; 17618c2ecf20Sopenharmony_ci return 0; 17628c2ecf20Sopenharmony_ci} 17638c2ecf20Sopenharmony_ci 17648c2ecf20Sopenharmony_cistatic void store_one(const char *name, struct cache_file_callback *cb) 17658c2ecf20Sopenharmony_ci{ 17668c2ecf20Sopenharmony_ci struct file *file = NULL; 17678c2ecf20Sopenharmony_ci char *fullname = NULL; 17688c2ecf20Sopenharmony_ci char *kvalue = NULL; 17698c2ecf20Sopenharmony_ci char cid[HMDFS_CFN_CID_SIZE]; 17708c2ecf20Sopenharmony_ci uint64_t hash; 17718c2ecf20Sopenharmony_ci ssize_t error; 17728c2ecf20Sopenharmony_ci 17738c2ecf20Sopenharmony_ci if (strlen(name) + strlen(cb->dirname) >= PATH_MAX) 17748c2ecf20Sopenharmony_ci return; 17758c2ecf20Sopenharmony_ci 17768c2ecf20Sopenharmony_ci fullname = kzalloc(PATH_MAX, GFP_KERNEL); 17778c2ecf20Sopenharmony_ci if (!fullname) 17788c2ecf20Sopenharmony_ci return; 17798c2ecf20Sopenharmony_ci 17808c2ecf20Sopenharmony_ci snprintf(fullname, PATH_MAX, "%s%s", cb->dirname, name); 17818c2ecf20Sopenharmony_ci 17828c2ecf20Sopenharmony_ci file = filp_open(fullname, O_RDWR | O_LARGEFILE, 0); 17838c2ecf20Sopenharmony_ci if (IS_ERR(file)) { 17848c2ecf20Sopenharmony_ci hmdfs_err("open fail %ld", PTR_ERR(file)); 17858c2ecf20Sopenharmony_ci goto out; 17868c2ecf20Sopenharmony_ci } 17878c2ecf20Sopenharmony_ci 17888c2ecf20Sopenharmony_ci kvalue = kzalloc(PATH_MAX, GFP_KERNEL); 17898c2ecf20Sopenharmony_ci if (!kvalue) 17908c2ecf20Sopenharmony_ci goto out_file; 17918c2ecf20Sopenharmony_ci 17928c2ecf20Sopenharmony_ci error = __vfs_getxattr(file_dentry(file), file_inode(file), 17938c2ecf20Sopenharmony_ci DENTRY_FILE_XATTR_NAME, kvalue, PATH_MAX); 17948c2ecf20Sopenharmony_ci if (error <= 0 || error >= PATH_MAX) { 17958c2ecf20Sopenharmony_ci hmdfs_err("getxattr return: %zd", error); 17968c2ecf20Sopenharmony_ci goto out_kvalue; 17978c2ecf20Sopenharmony_ci } 17988c2ecf20Sopenharmony_ci 17998c2ecf20Sopenharmony_ci kvalue[error] = '\0'; 18008c2ecf20Sopenharmony_ci cid[0] = '\0'; 18018c2ecf20Sopenharmony_ci 18028c2ecf20Sopenharmony_ci if (!cb->server) { 18038c2ecf20Sopenharmony_ci if (get_cid_and_hash(name, &hash, cid)) { 18048c2ecf20Sopenharmony_ci hmdfs_err("get cid and hash fail"); 18058c2ecf20Sopenharmony_ci goto out_kvalue; 18068c2ecf20Sopenharmony_ci } 18078c2ecf20Sopenharmony_ci } 18088c2ecf20Sopenharmony_ci 18098c2ecf20Sopenharmony_ci load_cfn(cb->sbi, fullname, kvalue, cid, cb->server); 18108c2ecf20Sopenharmony_ci 18118c2ecf20Sopenharmony_ciout_kvalue: 18128c2ecf20Sopenharmony_ci kfree(kvalue); 18138c2ecf20Sopenharmony_ciout_file: 18148c2ecf20Sopenharmony_ci filp_close(file, NULL); 18158c2ecf20Sopenharmony_ciout: 18168c2ecf20Sopenharmony_ci kfree(fullname); 18178c2ecf20Sopenharmony_ci} 18188c2ecf20Sopenharmony_ci 18198c2ecf20Sopenharmony_cistatic int cache_file_iterate(struct dir_context *ctx, const char *name, 18208c2ecf20Sopenharmony_ci int name_len, loff_t offset, u64 ino, 18218c2ecf20Sopenharmony_ci unsigned int d_type) 18228c2ecf20Sopenharmony_ci{ 18238c2ecf20Sopenharmony_ci struct cache_file_item *cfi = NULL; 18248c2ecf20Sopenharmony_ci struct cache_file_callback *cb = 18258c2ecf20Sopenharmony_ci container_of(ctx, struct cache_file_callback, ctx); 18268c2ecf20Sopenharmony_ci 18278c2ecf20Sopenharmony_ci if (name_len > NAME_MAX) { 18288c2ecf20Sopenharmony_ci hmdfs_err("name_len:%d NAME_MAX:%u", name_len, NAME_MAX); 18298c2ecf20Sopenharmony_ci return 0; 18308c2ecf20Sopenharmony_ci } 18318c2ecf20Sopenharmony_ci 18328c2ecf20Sopenharmony_ci if (d_type != DT_REG) 18338c2ecf20Sopenharmony_ci return 0; 18348c2ecf20Sopenharmony_ci 18358c2ecf20Sopenharmony_ci cfi = kmalloc(sizeof(*cfi), GFP_KERNEL); 18368c2ecf20Sopenharmony_ci if (!cfi) 18378c2ecf20Sopenharmony_ci return -ENOMEM; 18388c2ecf20Sopenharmony_ci 18398c2ecf20Sopenharmony_ci cfi->name = kstrndup(name, name_len, GFP_KERNEL); 18408c2ecf20Sopenharmony_ci if (!cfi->name) { 18418c2ecf20Sopenharmony_ci kfree(cfi); 18428c2ecf20Sopenharmony_ci return -ENOMEM; 18438c2ecf20Sopenharmony_ci } 18448c2ecf20Sopenharmony_ci 18458c2ecf20Sopenharmony_ci list_add_tail(&cfi->list, &cb->list); 18468c2ecf20Sopenharmony_ci 18478c2ecf20Sopenharmony_ci return 0; 18488c2ecf20Sopenharmony_ci} 18498c2ecf20Sopenharmony_ci 18508c2ecf20Sopenharmony_civoid hmdfs_do_load(struct hmdfs_sb_info *sbi, const char *fullname, bool server) 18518c2ecf20Sopenharmony_ci{ 18528c2ecf20Sopenharmony_ci struct file *file = NULL; 18538c2ecf20Sopenharmony_ci struct path dirpath; 18548c2ecf20Sopenharmony_ci int err; 18558c2ecf20Sopenharmony_ci struct cache_file_item *cfi = NULL; 18568c2ecf20Sopenharmony_ci struct cache_file_item *n = NULL; 18578c2ecf20Sopenharmony_ci struct cache_file_callback cb = { 18588c2ecf20Sopenharmony_ci .ctx.actor = cache_file_iterate, 18598c2ecf20Sopenharmony_ci .ctx.pos = 0, 18608c2ecf20Sopenharmony_ci .dirname = fullname, 18618c2ecf20Sopenharmony_ci .sbi = sbi, 18628c2ecf20Sopenharmony_ci .server = server, 18638c2ecf20Sopenharmony_ci }; 18648c2ecf20Sopenharmony_ci INIT_LIST_HEAD(&cb.list); 18658c2ecf20Sopenharmony_ci 18668c2ecf20Sopenharmony_ci 18678c2ecf20Sopenharmony_ci err = kern_path(fullname, LOOKUP_DIRECTORY, &dirpath); 18688c2ecf20Sopenharmony_ci if (err) { 18698c2ecf20Sopenharmony_ci hmdfs_info("No file path"); 18708c2ecf20Sopenharmony_ci return; 18718c2ecf20Sopenharmony_ci } 18728c2ecf20Sopenharmony_ci 18738c2ecf20Sopenharmony_ci file = dentry_open(&dirpath, O_RDONLY, current_cred()); 18748c2ecf20Sopenharmony_ci if (IS_ERR_OR_NULL(file)) { 18758c2ecf20Sopenharmony_ci hmdfs_err("dentry_open failed, error: %ld", PTR_ERR(file)); 18768c2ecf20Sopenharmony_ci path_put(&dirpath); 18778c2ecf20Sopenharmony_ci return; 18788c2ecf20Sopenharmony_ci } 18798c2ecf20Sopenharmony_ci 18808c2ecf20Sopenharmony_ci err = iterate_dir(file, &cb.ctx); 18818c2ecf20Sopenharmony_ci if (err) 18828c2ecf20Sopenharmony_ci hmdfs_err("iterate_dir failed, err: %d", err); 18838c2ecf20Sopenharmony_ci 18848c2ecf20Sopenharmony_ci list_for_each_entry_safe(cfi, n, &cb.list, list) { 18858c2ecf20Sopenharmony_ci store_one(cfi->name, &cb); 18868c2ecf20Sopenharmony_ci list_del_init(&cfi->list); 18878c2ecf20Sopenharmony_ci kfree(cfi->name); 18888c2ecf20Sopenharmony_ci kfree(cfi); 18898c2ecf20Sopenharmony_ci } 18908c2ecf20Sopenharmony_ci 18918c2ecf20Sopenharmony_ci fput(file); 18928c2ecf20Sopenharmony_ci path_put(&dirpath); 18938c2ecf20Sopenharmony_ci} 18948c2ecf20Sopenharmony_ci 18958c2ecf20Sopenharmony_ci/** 18968c2ecf20Sopenharmony_ci * This function just used for delete dentryfile.dat 18978c2ecf20Sopenharmony_ci */ 18988c2ecf20Sopenharmony_ciint delete_dentry_file(struct file *filp) 18998c2ecf20Sopenharmony_ci{ 19008c2ecf20Sopenharmony_ci int err = 0; 19018c2ecf20Sopenharmony_ci struct dentry *dentry = file_dentry(filp); 19028c2ecf20Sopenharmony_ci struct dentry *parent = lock_parent(dentry); 19038c2ecf20Sopenharmony_ci 19048c2ecf20Sopenharmony_ci if (dentry->d_parent == parent) { 19058c2ecf20Sopenharmony_ci dget(dentry); 19068c2ecf20Sopenharmony_ci err = vfs_unlink(d_inode(parent), dentry, NULL); 19078c2ecf20Sopenharmony_ci dput(dentry); 19088c2ecf20Sopenharmony_ci } 19098c2ecf20Sopenharmony_ci unlock_dir(parent); 19108c2ecf20Sopenharmony_ci 19118c2ecf20Sopenharmony_ci return err; 19128c2ecf20Sopenharmony_ci} 19138c2ecf20Sopenharmony_ci 19148c2ecf20Sopenharmony_civoid hmdfs_delete_useless_cfn(struct hmdfs_sb_info *sbi) 19158c2ecf20Sopenharmony_ci{ 19168c2ecf20Sopenharmony_ci struct cache_file_node *cfn = NULL; 19178c2ecf20Sopenharmony_ci struct cache_file_node *n = NULL; 19188c2ecf20Sopenharmony_ci 19198c2ecf20Sopenharmony_ci mutex_lock(&sbi->cache_list_lock); 19208c2ecf20Sopenharmony_ci 19218c2ecf20Sopenharmony_ci list_for_each_entry_safe(cfn, n, &sbi->to_delete, list) { 19228c2ecf20Sopenharmony_ci delete_dentry_file(cfn->filp); 19238c2ecf20Sopenharmony_ci list_del_init(&cfn->list); 19248c2ecf20Sopenharmony_ci release_cfn(cfn); 19258c2ecf20Sopenharmony_ci } 19268c2ecf20Sopenharmony_ci mutex_unlock(&sbi->cache_list_lock); 19278c2ecf20Sopenharmony_ci} 19288c2ecf20Sopenharmony_ci 19298c2ecf20Sopenharmony_civoid hmdfs_cfn_load(struct hmdfs_sb_info *sbi) 19308c2ecf20Sopenharmony_ci{ 19318c2ecf20Sopenharmony_ci char *fullname = NULL; 19328c2ecf20Sopenharmony_ci 19338c2ecf20Sopenharmony_ci if (!sbi->s_dentry_cache) 19348c2ecf20Sopenharmony_ci return; 19358c2ecf20Sopenharmony_ci 19368c2ecf20Sopenharmony_ci fullname = kzalloc(PATH_MAX, GFP_KERNEL); 19378c2ecf20Sopenharmony_ci if (!fullname) 19388c2ecf20Sopenharmony_ci return; 19398c2ecf20Sopenharmony_ci 19408c2ecf20Sopenharmony_ci snprintf(fullname, PATH_MAX, "%s/dentry_cache/client/", 19418c2ecf20Sopenharmony_ci sbi->cache_dir); 19428c2ecf20Sopenharmony_ci hmdfs_do_load(sbi, fullname, false); 19438c2ecf20Sopenharmony_ci 19448c2ecf20Sopenharmony_ci snprintf(fullname, PATH_MAX, "%s/dentry_cache/server/", 19458c2ecf20Sopenharmony_ci sbi->cache_dir); 19468c2ecf20Sopenharmony_ci hmdfs_do_load(sbi, fullname, true); 19478c2ecf20Sopenharmony_ci 19488c2ecf20Sopenharmony_ci kfree(fullname); 19498c2ecf20Sopenharmony_ci 19508c2ecf20Sopenharmony_ci hmdfs_delete_useless_cfn(sbi); 19518c2ecf20Sopenharmony_ci} 19528c2ecf20Sopenharmony_ci 19538c2ecf20Sopenharmony_cistatic void __cache_file_destroy_by_path(struct list_head *head, 19548c2ecf20Sopenharmony_ci const char *path) 19558c2ecf20Sopenharmony_ci{ 19568c2ecf20Sopenharmony_ci struct cache_file_node *cfn = NULL; 19578c2ecf20Sopenharmony_ci struct cache_file_node *n = NULL; 19588c2ecf20Sopenharmony_ci 19598c2ecf20Sopenharmony_ci list_for_each_entry_safe(cfn, n, head, list) { 19608c2ecf20Sopenharmony_ci if (strcmp(path, cfn->relative_path) != 0) 19618c2ecf20Sopenharmony_ci continue; 19628c2ecf20Sopenharmony_ci list_del_init(&cfn->list); 19638c2ecf20Sopenharmony_ci delete_dentry_file(cfn->filp); 19648c2ecf20Sopenharmony_ci release_cfn(cfn); 19658c2ecf20Sopenharmony_ci } 19668c2ecf20Sopenharmony_ci} 19678c2ecf20Sopenharmony_ci 19688c2ecf20Sopenharmony_cistatic void cache_file_destroy_by_path(struct hmdfs_sb_info *sbi, 19698c2ecf20Sopenharmony_ci const char *path) 19708c2ecf20Sopenharmony_ci{ 19718c2ecf20Sopenharmony_ci mutex_lock(&sbi->cache_list_lock); 19728c2ecf20Sopenharmony_ci 19738c2ecf20Sopenharmony_ci __cache_file_destroy_by_path(&sbi->server_cache, path); 19748c2ecf20Sopenharmony_ci __cache_file_destroy_by_path(&sbi->client_cache, path); 19758c2ecf20Sopenharmony_ci 19768c2ecf20Sopenharmony_ci mutex_unlock(&sbi->cache_list_lock); 19778c2ecf20Sopenharmony_ci} 19788c2ecf20Sopenharmony_ci 19798c2ecf20Sopenharmony_cistatic void cache_file_find_and_delete(struct hmdfs_peer *con, 19808c2ecf20Sopenharmony_ci const char *relative_path) 19818c2ecf20Sopenharmony_ci{ 19828c2ecf20Sopenharmony_ci struct cache_file_node *cfn; 19838c2ecf20Sopenharmony_ci 19848c2ecf20Sopenharmony_ci cfn = find_cfn(con->sbi, con->cid, relative_path, false); 19858c2ecf20Sopenharmony_ci if (!cfn) 19868c2ecf20Sopenharmony_ci return; 19878c2ecf20Sopenharmony_ci 19888c2ecf20Sopenharmony_ci remove_cfn(cfn); 19898c2ecf20Sopenharmony_ci release_cfn(cfn); 19908c2ecf20Sopenharmony_ci} 19918c2ecf20Sopenharmony_ci 19928c2ecf20Sopenharmony_civoid cache_file_delete_by_dentry(struct hmdfs_peer *con, struct dentry *dentry) 19938c2ecf20Sopenharmony_ci{ 19948c2ecf20Sopenharmony_ci char *relative_path = NULL; 19958c2ecf20Sopenharmony_ci 19968c2ecf20Sopenharmony_ci relative_path = hmdfs_get_dentry_relative_path(dentry); 19978c2ecf20Sopenharmony_ci if (unlikely(!relative_path)) { 19988c2ecf20Sopenharmony_ci hmdfs_err("get relative path failed %d", -ENOMEM); 19998c2ecf20Sopenharmony_ci return; 20008c2ecf20Sopenharmony_ci } 20018c2ecf20Sopenharmony_ci cache_file_find_and_delete(con, relative_path); 20028c2ecf20Sopenharmony_ci kfree(relative_path); 20038c2ecf20Sopenharmony_ci} 20048c2ecf20Sopenharmony_ci 20058c2ecf20Sopenharmony_cistruct file *hmdfs_get_new_dentry_file(struct hmdfs_peer *con, 20068c2ecf20Sopenharmony_ci const char *relative_path, 20078c2ecf20Sopenharmony_ci struct hmdfs_dcache_header *header) 20088c2ecf20Sopenharmony_ci{ 20098c2ecf20Sopenharmony_ci struct hmdfs_sb_info *sbi = con->sbi; 20108c2ecf20Sopenharmony_ci int len = strlen(relative_path); 20118c2ecf20Sopenharmony_ci struct file *filp = NULL; 20128c2ecf20Sopenharmony_ci int err; 20138c2ecf20Sopenharmony_ci 20148c2ecf20Sopenharmony_ci filp = create_local_dentry_file_cache(sbi); 20158c2ecf20Sopenharmony_ci if (IS_ERR(filp)) 20168c2ecf20Sopenharmony_ci return filp; 20178c2ecf20Sopenharmony_ci 20188c2ecf20Sopenharmony_ci err = hmdfs_client_start_readdir(con, filp, relative_path, len, header); 20198c2ecf20Sopenharmony_ci if (err) { 20208c2ecf20Sopenharmony_ci if (err != -ENOENT) 20218c2ecf20Sopenharmony_ci hmdfs_err("readdir failed dev: %llu err: %d", 20228c2ecf20Sopenharmony_ci con->device_id, err); 20238c2ecf20Sopenharmony_ci fput(filp); 20248c2ecf20Sopenharmony_ci filp = ERR_PTR(err); 20258c2ecf20Sopenharmony_ci } 20268c2ecf20Sopenharmony_ci 20278c2ecf20Sopenharmony_ci return filp; 20288c2ecf20Sopenharmony_ci} 20298c2ecf20Sopenharmony_ci 20308c2ecf20Sopenharmony_civoid add_cfn_to_item(struct dentry *dentry, struct hmdfs_peer *con, 20318c2ecf20Sopenharmony_ci struct cache_file_node *cfn) 20328c2ecf20Sopenharmony_ci{ 20338c2ecf20Sopenharmony_ci struct file *file = cfn->filp; 20348c2ecf20Sopenharmony_ci int err; 20358c2ecf20Sopenharmony_ci 20368c2ecf20Sopenharmony_ci err = hmdfs_add_cache_list(con->device_id, dentry, file); 20378c2ecf20Sopenharmony_ci if (unlikely(err)) { 20388c2ecf20Sopenharmony_ci hmdfs_err("add cache list failed devid:%llu err:%d", 20398c2ecf20Sopenharmony_ci con->device_id, err); 20408c2ecf20Sopenharmony_ci return; 20418c2ecf20Sopenharmony_ci } 20428c2ecf20Sopenharmony_ci} 20438c2ecf20Sopenharmony_ci 20448c2ecf20Sopenharmony_ciint hmdfs_add_file_to_cache(struct dentry *dentry, struct hmdfs_peer *con, 20458c2ecf20Sopenharmony_ci struct file *file, const char *relative_path) 20468c2ecf20Sopenharmony_ci{ 20478c2ecf20Sopenharmony_ci struct hmdfs_sb_info *sbi = con->sbi; 20488c2ecf20Sopenharmony_ci struct file *newf = file; 20498c2ecf20Sopenharmony_ci 20508c2ecf20Sopenharmony_ci if (cache_get_dentry_count(sbi, file) >= sbi->dcache_threshold) 20518c2ecf20Sopenharmony_ci newf = cache_file_persistent(con, file, relative_path, false); 20528c2ecf20Sopenharmony_ci else 20538c2ecf20Sopenharmony_ci cache_file_find_and_delete(con, relative_path); 20548c2ecf20Sopenharmony_ci 20558c2ecf20Sopenharmony_ci return hmdfs_add_cache_list(con->device_id, dentry, newf); 20568c2ecf20Sopenharmony_ci} 20578c2ecf20Sopenharmony_ci 20588c2ecf20Sopenharmony_cistatic struct file *read_header_and_revalidate(struct hmdfs_peer *con, 20598c2ecf20Sopenharmony_ci struct file *filp, 20608c2ecf20Sopenharmony_ci const char *relative_path) 20618c2ecf20Sopenharmony_ci{ 20628c2ecf20Sopenharmony_ci struct hmdfs_dcache_header header; 20638c2ecf20Sopenharmony_ci struct hmdfs_dcache_header *p = NULL; 20648c2ecf20Sopenharmony_ci 20658c2ecf20Sopenharmony_ci if (read_header(con->sbi, filp, &header) == 0) 20668c2ecf20Sopenharmony_ci p = &header; 20678c2ecf20Sopenharmony_ci 20688c2ecf20Sopenharmony_ci return hmdfs_get_new_dentry_file(con, relative_path, p); 20698c2ecf20Sopenharmony_ci} 20708c2ecf20Sopenharmony_ci 20718c2ecf20Sopenharmony_civoid remote_file_revalidate_cfn(struct dentry *dentry, struct hmdfs_peer *con, 20728c2ecf20Sopenharmony_ci struct cache_file_node *cfn, 20738c2ecf20Sopenharmony_ci const char *relative_path) 20748c2ecf20Sopenharmony_ci{ 20758c2ecf20Sopenharmony_ci struct file *file = NULL; 20768c2ecf20Sopenharmony_ci int err; 20778c2ecf20Sopenharmony_ci 20788c2ecf20Sopenharmony_ci file = read_header_and_revalidate(con, cfn->filp, relative_path); 20798c2ecf20Sopenharmony_ci if (IS_ERR(file)) 20808c2ecf20Sopenharmony_ci return; 20818c2ecf20Sopenharmony_ci 20828c2ecf20Sopenharmony_ci /* 20838c2ecf20Sopenharmony_ci * If the request returned ok but file length is 0, we assume 20848c2ecf20Sopenharmony_ci * that the server verified the client cache file is uptodate. 20858c2ecf20Sopenharmony_ci */ 20868c2ecf20Sopenharmony_ci if (i_size_read(file->f_inode) == 0) { 20878c2ecf20Sopenharmony_ci hmdfs_info("The cfn cache for dev:%llu is uptodate", 20888c2ecf20Sopenharmony_ci con->device_id); 20898c2ecf20Sopenharmony_ci fput(file); 20908c2ecf20Sopenharmony_ci add_cfn_to_item(dentry, con, cfn); 20918c2ecf20Sopenharmony_ci return; 20928c2ecf20Sopenharmony_ci } 20938c2ecf20Sopenharmony_ci 20948c2ecf20Sopenharmony_ci /* OK, cfn is not uptodate, let's remove it and add the new file */ 20958c2ecf20Sopenharmony_ci remove_cfn(cfn); 20968c2ecf20Sopenharmony_ci 20978c2ecf20Sopenharmony_ci err = hmdfs_add_file_to_cache(dentry, con, file, relative_path); 20988c2ecf20Sopenharmony_ci if (unlikely(err)) 20998c2ecf20Sopenharmony_ci hmdfs_err("add cache list failed devid:%llu err:%d", 21008c2ecf20Sopenharmony_ci con->device_id, err); 21018c2ecf20Sopenharmony_ci fput(file); 21028c2ecf20Sopenharmony_ci} 21038c2ecf20Sopenharmony_ci 21048c2ecf20Sopenharmony_civoid remote_file_revalidate_item(struct dentry *dentry, struct hmdfs_peer *con, 21058c2ecf20Sopenharmony_ci struct clearcache_item *item, 21068c2ecf20Sopenharmony_ci const char *relative_path) 21078c2ecf20Sopenharmony_ci{ 21088c2ecf20Sopenharmony_ci struct file *file = NULL; 21098c2ecf20Sopenharmony_ci int err; 21108c2ecf20Sopenharmony_ci 21118c2ecf20Sopenharmony_ci file = read_header_and_revalidate(con, item->filp, relative_path); 21128c2ecf20Sopenharmony_ci if (IS_ERR(file)) 21138c2ecf20Sopenharmony_ci return; 21148c2ecf20Sopenharmony_ci 21158c2ecf20Sopenharmony_ci /* 21168c2ecf20Sopenharmony_ci * If the request returned ok but file length is 0, we assume 21178c2ecf20Sopenharmony_ci * that the server verified the client cache file is uptodate. 21188c2ecf20Sopenharmony_ci */ 21198c2ecf20Sopenharmony_ci if (i_size_read(file->f_inode) == 0) { 21208c2ecf20Sopenharmony_ci hmdfs_info("The item cache for dev:%llu is uptodate", 21218c2ecf20Sopenharmony_ci con->device_id); 21228c2ecf20Sopenharmony_ci item->time = jiffies; 21238c2ecf20Sopenharmony_ci fput(file); 21248c2ecf20Sopenharmony_ci return; 21258c2ecf20Sopenharmony_ci } 21268c2ecf20Sopenharmony_ci 21278c2ecf20Sopenharmony_ci /* We need to replace the old item */ 21288c2ecf20Sopenharmony_ci remove_cache_item(item); 21298c2ecf20Sopenharmony_ci cache_file_find_and_delete(con, relative_path); 21308c2ecf20Sopenharmony_ci 21318c2ecf20Sopenharmony_ci err = hmdfs_add_file_to_cache(dentry, con, file, relative_path); 21328c2ecf20Sopenharmony_ci if (unlikely(err)) 21338c2ecf20Sopenharmony_ci hmdfs_err("add cache list failed devid:%llu err:%d", 21348c2ecf20Sopenharmony_ci con->device_id, err); 21358c2ecf20Sopenharmony_ci fput(file); 21368c2ecf20Sopenharmony_ci} 21378c2ecf20Sopenharmony_ci 21388c2ecf20Sopenharmony_cibool get_remote_dentry_file(struct dentry *dentry, struct hmdfs_peer *con) 21398c2ecf20Sopenharmony_ci{ 21408c2ecf20Sopenharmony_ci struct hmdfs_dentry_info *d_info = hmdfs_d(dentry); 21418c2ecf20Sopenharmony_ci struct cache_file_node *cfn = NULL; 21428c2ecf20Sopenharmony_ci struct hmdfs_sb_info *sbi = con->sbi; 21438c2ecf20Sopenharmony_ci char *relative_path = NULL; 21448c2ecf20Sopenharmony_ci int err = 0; 21458c2ecf20Sopenharmony_ci struct file *filp = NULL; 21468c2ecf20Sopenharmony_ci struct clearcache_item *item; 21478c2ecf20Sopenharmony_ci 21488c2ecf20Sopenharmony_ci if (hmdfs_cache_revalidate(READ_ONCE(con->conn_time), con->device_id, 21498c2ecf20Sopenharmony_ci dentry)) 21508c2ecf20Sopenharmony_ci return false; 21518c2ecf20Sopenharmony_ci 21528c2ecf20Sopenharmony_ci relative_path = hmdfs_get_dentry_relative_path(dentry); 21538c2ecf20Sopenharmony_ci if (unlikely(!relative_path)) { 21548c2ecf20Sopenharmony_ci hmdfs_err("get relative path failed %d", -ENOMEM); 21558c2ecf20Sopenharmony_ci return false; 21568c2ecf20Sopenharmony_ci } 21578c2ecf20Sopenharmony_ci mutex_lock(&d_info->cache_pull_lock); 21588c2ecf20Sopenharmony_ci if (hmdfs_cache_revalidate(READ_ONCE(con->conn_time), con->device_id, 21598c2ecf20Sopenharmony_ci dentry)) 21608c2ecf20Sopenharmony_ci goto out_unlock; 21618c2ecf20Sopenharmony_ci 21628c2ecf20Sopenharmony_ci item = hmdfs_find_cache_item(con->device_id, dentry); 21638c2ecf20Sopenharmony_ci if (item) { 21648c2ecf20Sopenharmony_ci remote_file_revalidate_item(dentry, con, item, relative_path); 21658c2ecf20Sopenharmony_ci kref_put(&item->ref, release_cache_item); 21668c2ecf20Sopenharmony_ci goto out_unlock; 21678c2ecf20Sopenharmony_ci } 21688c2ecf20Sopenharmony_ci 21698c2ecf20Sopenharmony_ci cfn = find_cfn(sbi, con->cid, relative_path, false); 21708c2ecf20Sopenharmony_ci if (cfn) { 21718c2ecf20Sopenharmony_ci remote_file_revalidate_cfn(dentry, con, cfn, relative_path); 21728c2ecf20Sopenharmony_ci release_cfn(cfn); 21738c2ecf20Sopenharmony_ci goto out_unlock; 21748c2ecf20Sopenharmony_ci } 21758c2ecf20Sopenharmony_ci 21768c2ecf20Sopenharmony_ci filp = hmdfs_get_new_dentry_file(con, relative_path, NULL); 21778c2ecf20Sopenharmony_ci if (IS_ERR(filp)) { 21788c2ecf20Sopenharmony_ci err = PTR_ERR(filp); 21798c2ecf20Sopenharmony_ci goto out_unlock; 21808c2ecf20Sopenharmony_ci } 21818c2ecf20Sopenharmony_ci 21828c2ecf20Sopenharmony_ci err = hmdfs_add_file_to_cache(dentry, con, filp, relative_path); 21838c2ecf20Sopenharmony_ci if (unlikely(err)) 21848c2ecf20Sopenharmony_ci hmdfs_err("add cache list failed devid:%lu err:%d", 21858c2ecf20Sopenharmony_ci (unsigned long)con->device_id, err); 21868c2ecf20Sopenharmony_ci fput(filp); 21878c2ecf20Sopenharmony_ci 21888c2ecf20Sopenharmony_ciout_unlock: 21898c2ecf20Sopenharmony_ci mutex_unlock(&d_info->cache_pull_lock); 21908c2ecf20Sopenharmony_ci if (err && err != -ENOENT) 21918c2ecf20Sopenharmony_ci hmdfs_err("readdir failed dev:%lu err:%d", 21928c2ecf20Sopenharmony_ci (unsigned long)con->device_id, err); 21938c2ecf20Sopenharmony_ci kfree(relative_path); 21948c2ecf20Sopenharmony_ci return true; 21958c2ecf20Sopenharmony_ci} 21968c2ecf20Sopenharmony_ci 21978c2ecf20Sopenharmony_ciint hmdfs_file_type(const char *name) 21988c2ecf20Sopenharmony_ci{ 21998c2ecf20Sopenharmony_ci if (!name) 22008c2ecf20Sopenharmony_ci return -EINVAL; 22018c2ecf20Sopenharmony_ci 22028c2ecf20Sopenharmony_ci if (!strcmp(name, CURRENT_DIR) || !strcmp(name, PARENT_DIR)) 22038c2ecf20Sopenharmony_ci return HMDFS_TYPE_DOT; 22048c2ecf20Sopenharmony_ci 22058c2ecf20Sopenharmony_ci return HMDFS_TYPE_COMMON; 22068c2ecf20Sopenharmony_ci} 22078c2ecf20Sopenharmony_ci 22088c2ecf20Sopenharmony_cistruct clearcache_item *hmdfs_find_cache_item(uint64_t dev_id, 22098c2ecf20Sopenharmony_ci struct dentry *dentry) 22108c2ecf20Sopenharmony_ci{ 22118c2ecf20Sopenharmony_ci struct clearcache_item *item = NULL; 22128c2ecf20Sopenharmony_ci struct hmdfs_dentry_info *d_info = hmdfs_d(dentry); 22138c2ecf20Sopenharmony_ci 22148c2ecf20Sopenharmony_ci if (!d_info) 22158c2ecf20Sopenharmony_ci return NULL; 22168c2ecf20Sopenharmony_ci 22178c2ecf20Sopenharmony_ci spin_lock(&d_info->cache_list_lock); 22188c2ecf20Sopenharmony_ci list_for_each_entry(item, &(d_info->cache_list_head), list) { 22198c2ecf20Sopenharmony_ci if (dev_id == item->dev_id) { 22208c2ecf20Sopenharmony_ci kref_get(&item->ref); 22218c2ecf20Sopenharmony_ci spin_unlock(&d_info->cache_list_lock); 22228c2ecf20Sopenharmony_ci return item; 22238c2ecf20Sopenharmony_ci } 22248c2ecf20Sopenharmony_ci } 22258c2ecf20Sopenharmony_ci spin_unlock(&d_info->cache_list_lock); 22268c2ecf20Sopenharmony_ci return NULL; 22278c2ecf20Sopenharmony_ci} 22288c2ecf20Sopenharmony_ci 22298c2ecf20Sopenharmony_cibool hmdfs_cache_revalidate(unsigned long conn_time, uint64_t dev_id, 22308c2ecf20Sopenharmony_ci struct dentry *dentry) 22318c2ecf20Sopenharmony_ci{ 22328c2ecf20Sopenharmony_ci bool ret = false; 22338c2ecf20Sopenharmony_ci struct clearcache_item *item = NULL; 22348c2ecf20Sopenharmony_ci struct hmdfs_dentry_info *d_info = hmdfs_d(dentry); 22358c2ecf20Sopenharmony_ci unsigned int timeout; 22368c2ecf20Sopenharmony_ci 22378c2ecf20Sopenharmony_ci if (!d_info) 22388c2ecf20Sopenharmony_ci return ret; 22398c2ecf20Sopenharmony_ci 22408c2ecf20Sopenharmony_ci timeout = hmdfs_sb(dentry->d_sb)->dcache_timeout; 22418c2ecf20Sopenharmony_ci spin_lock(&d_info->cache_list_lock); 22428c2ecf20Sopenharmony_ci list_for_each_entry(item, &(d_info->cache_list_head), list) { 22438c2ecf20Sopenharmony_ci if (dev_id == item->dev_id) { 22448c2ecf20Sopenharmony_ci ret = cache_item_revalidate(conn_time, item->time, 22458c2ecf20Sopenharmony_ci timeout); 22468c2ecf20Sopenharmony_ci break; 22478c2ecf20Sopenharmony_ci } 22488c2ecf20Sopenharmony_ci } 22498c2ecf20Sopenharmony_ci spin_unlock(&d_info->cache_list_lock); 22508c2ecf20Sopenharmony_ci return ret; 22518c2ecf20Sopenharmony_ci} 22528c2ecf20Sopenharmony_ci 22538c2ecf20Sopenharmony_civoid remove_cache_item(struct clearcache_item *item) 22548c2ecf20Sopenharmony_ci{ 22558c2ecf20Sopenharmony_ci bool deleted; 22568c2ecf20Sopenharmony_ci 22578c2ecf20Sopenharmony_ci spin_lock(&item->d_info->cache_list_lock); 22588c2ecf20Sopenharmony_ci deleted = list_empty(&item->list); 22598c2ecf20Sopenharmony_ci if (!deleted) 22608c2ecf20Sopenharmony_ci list_del_init(&item->list); 22618c2ecf20Sopenharmony_ci spin_unlock(&item->d_info->cache_list_lock); 22628c2ecf20Sopenharmony_ci if (!deleted) 22638c2ecf20Sopenharmony_ci kref_put(&item->ref, release_cache_item); 22648c2ecf20Sopenharmony_ci} 22658c2ecf20Sopenharmony_ci 22668c2ecf20Sopenharmony_civoid release_cache_item(struct kref *ref) 22678c2ecf20Sopenharmony_ci{ 22688c2ecf20Sopenharmony_ci struct clearcache_item *item = 22698c2ecf20Sopenharmony_ci container_of(ref, struct clearcache_item, ref); 22708c2ecf20Sopenharmony_ci 22718c2ecf20Sopenharmony_ci if (item->filp) 22728c2ecf20Sopenharmony_ci fput(item->filp); 22738c2ecf20Sopenharmony_ci kfree(item); 22748c2ecf20Sopenharmony_ci} 22758c2ecf20Sopenharmony_ci 22768c2ecf20Sopenharmony_civoid hmdfs_remove_cache_filp(struct hmdfs_peer *con, struct dentry *dentry) 22778c2ecf20Sopenharmony_ci{ 22788c2ecf20Sopenharmony_ci struct clearcache_item *item = NULL; 22798c2ecf20Sopenharmony_ci struct clearcache_item *item_temp = NULL; 22808c2ecf20Sopenharmony_ci struct hmdfs_dentry_info *d_info = hmdfs_d(dentry); 22818c2ecf20Sopenharmony_ci // struct path *lower_path = NULL; 22828c2ecf20Sopenharmony_ci 22838c2ecf20Sopenharmony_ci if (!d_info) 22848c2ecf20Sopenharmony_ci return; 22858c2ecf20Sopenharmony_ci 22868c2ecf20Sopenharmony_ci spin_lock(&d_info->cache_list_lock); 22878c2ecf20Sopenharmony_ci list_for_each_entry_safe(item, item_temp, &(d_info->cache_list_head), 22888c2ecf20Sopenharmony_ci list) { 22898c2ecf20Sopenharmony_ci if (con->device_id == item->dev_id) { 22908c2ecf20Sopenharmony_ci list_del_init(&item->list); 22918c2ecf20Sopenharmony_ci spin_unlock(&d_info->cache_list_lock); 22928c2ecf20Sopenharmony_ci cache_file_delete_by_dentry(con, dentry); 22938c2ecf20Sopenharmony_ci kref_put(&item->ref, release_cache_item); 22948c2ecf20Sopenharmony_ci return; 22958c2ecf20Sopenharmony_ci } 22968c2ecf20Sopenharmony_ci } 22978c2ecf20Sopenharmony_ci spin_unlock(&d_info->cache_list_lock); 22988c2ecf20Sopenharmony_ci} 22998c2ecf20Sopenharmony_ci 23008c2ecf20Sopenharmony_ciint hmdfs_add_cache_list(uint64_t dev_id, struct dentry *dentry, 23018c2ecf20Sopenharmony_ci struct file *filp) 23028c2ecf20Sopenharmony_ci{ 23038c2ecf20Sopenharmony_ci struct clearcache_item *item = NULL; 23048c2ecf20Sopenharmony_ci struct hmdfs_dentry_info *d_info = hmdfs_d(dentry); 23058c2ecf20Sopenharmony_ci 23068c2ecf20Sopenharmony_ci if (!d_info) 23078c2ecf20Sopenharmony_ci return -ENOMEM; 23088c2ecf20Sopenharmony_ci 23098c2ecf20Sopenharmony_ci item = kzalloc(sizeof(*item), GFP_KERNEL); 23108c2ecf20Sopenharmony_ci if (!item) 23118c2ecf20Sopenharmony_ci return -ENOMEM; 23128c2ecf20Sopenharmony_ci 23138c2ecf20Sopenharmony_ci item->dev_id = dev_id; 23148c2ecf20Sopenharmony_ci item->filp = get_file(filp); 23158c2ecf20Sopenharmony_ci item->time = jiffies; 23168c2ecf20Sopenharmony_ci item->d_info = d_info; 23178c2ecf20Sopenharmony_ci kref_init(&item->ref); 23188c2ecf20Sopenharmony_ci spin_lock(&d_info->cache_list_lock); 23198c2ecf20Sopenharmony_ci list_add_tail(&(item->list), &(d_info->cache_list_head)); 23208c2ecf20Sopenharmony_ci spin_unlock(&d_info->cache_list_lock); 23218c2ecf20Sopenharmony_ci return 0; 23228c2ecf20Sopenharmony_ci} 23238c2ecf20Sopenharmony_ci 23248c2ecf20Sopenharmony_civoid hmdfs_add_remote_cache_list(struct hmdfs_peer *con, const char *dir_path) 23258c2ecf20Sopenharmony_ci{ 23268c2ecf20Sopenharmony_ci int err = 0; 23278c2ecf20Sopenharmony_ci struct remotecache_item *item = NULL; 23288c2ecf20Sopenharmony_ci struct remotecache_item *item_temp = NULL; 23298c2ecf20Sopenharmony_ci struct path path, root_path; 23308c2ecf20Sopenharmony_ci struct hmdfs_dentry_info *d_info = NULL; 23318c2ecf20Sopenharmony_ci 23328c2ecf20Sopenharmony_ci err = kern_path(con->sbi->local_dst, 0, &root_path); 23338c2ecf20Sopenharmony_ci if (err) { 23348c2ecf20Sopenharmony_ci hmdfs_err("kern_path failed err = %d", err); 23358c2ecf20Sopenharmony_ci return; 23368c2ecf20Sopenharmony_ci } 23378c2ecf20Sopenharmony_ci 23388c2ecf20Sopenharmony_ci err = vfs_path_lookup(root_path.dentry, root_path.mnt, dir_path, 0, 23398c2ecf20Sopenharmony_ci &path); 23408c2ecf20Sopenharmony_ci if (err) 23418c2ecf20Sopenharmony_ci goto out_put_root; 23428c2ecf20Sopenharmony_ci 23438c2ecf20Sopenharmony_ci d_info = hmdfs_d(path.dentry); 23448c2ecf20Sopenharmony_ci if (!d_info) { 23458c2ecf20Sopenharmony_ci err = -EINVAL; 23468c2ecf20Sopenharmony_ci goto out; 23478c2ecf20Sopenharmony_ci } 23488c2ecf20Sopenharmony_ci 23498c2ecf20Sopenharmony_ci /* find duplicate con */ 23508c2ecf20Sopenharmony_ci mutex_lock(&d_info->remote_cache_list_lock); 23518c2ecf20Sopenharmony_ci list_for_each_entry_safe(item, item_temp, 23528c2ecf20Sopenharmony_ci &(d_info->remote_cache_list_head), list) { 23538c2ecf20Sopenharmony_ci if (item->con->device_id == con->device_id) { 23548c2ecf20Sopenharmony_ci mutex_unlock(&d_info->remote_cache_list_lock); 23558c2ecf20Sopenharmony_ci goto out; 23568c2ecf20Sopenharmony_ci } 23578c2ecf20Sopenharmony_ci } 23588c2ecf20Sopenharmony_ci 23598c2ecf20Sopenharmony_ci item = kzalloc(sizeof(*item), GFP_KERNEL); 23608c2ecf20Sopenharmony_ci if (!item) { 23618c2ecf20Sopenharmony_ci err = -ENOMEM; 23628c2ecf20Sopenharmony_ci mutex_unlock(&d_info->remote_cache_list_lock); 23638c2ecf20Sopenharmony_ci goto out; 23648c2ecf20Sopenharmony_ci } 23658c2ecf20Sopenharmony_ci 23668c2ecf20Sopenharmony_ci item->con = con; 23678c2ecf20Sopenharmony_ci item->drop_flag = 0; 23688c2ecf20Sopenharmony_ci list_add(&(item->list), &(d_info->remote_cache_list_head)); 23698c2ecf20Sopenharmony_ci mutex_unlock(&d_info->remote_cache_list_lock); 23708c2ecf20Sopenharmony_ci 23718c2ecf20Sopenharmony_ciout: 23728c2ecf20Sopenharmony_ci path_put(&path); 23738c2ecf20Sopenharmony_ciout_put_root: 23748c2ecf20Sopenharmony_ci path_put(&root_path); 23758c2ecf20Sopenharmony_ci} 23768c2ecf20Sopenharmony_ci 23778c2ecf20Sopenharmony_ciint hmdfs_drop_remote_cache_dents(struct dentry *dentry) 23788c2ecf20Sopenharmony_ci{ 23798c2ecf20Sopenharmony_ci struct path lower_path; 23808c2ecf20Sopenharmony_ci struct inode *lower_inode = NULL; 23818c2ecf20Sopenharmony_ci struct remotecache_item *item = NULL; 23828c2ecf20Sopenharmony_ci struct remotecache_item *item_temp = NULL; 23838c2ecf20Sopenharmony_ci struct hmdfs_dentry_info *d_info = NULL; 23848c2ecf20Sopenharmony_ci char *relative_path = NULL; 23858c2ecf20Sopenharmony_ci 23868c2ecf20Sopenharmony_ci if (!dentry) { 23878c2ecf20Sopenharmony_ci hmdfs_err("dentry null and return"); 23888c2ecf20Sopenharmony_ci return 0; 23898c2ecf20Sopenharmony_ci } 23908c2ecf20Sopenharmony_ci 23918c2ecf20Sopenharmony_ci d_info = hmdfs_d(dentry); 23928c2ecf20Sopenharmony_ci if (!d_info) { 23938c2ecf20Sopenharmony_ci hmdfs_err("d_info null and return"); 23948c2ecf20Sopenharmony_ci return 0; 23958c2ecf20Sopenharmony_ci } 23968c2ecf20Sopenharmony_ci hmdfs_get_lower_path(dentry, &lower_path); 23978c2ecf20Sopenharmony_ci if (IS_ERR_OR_NULL(lower_path.dentry)) { 23988c2ecf20Sopenharmony_ci hmdfs_put_lower_path(&lower_path); 23998c2ecf20Sopenharmony_ci return 0; 24008c2ecf20Sopenharmony_ci } 24018c2ecf20Sopenharmony_ci lower_inode = d_inode(lower_path.dentry); 24028c2ecf20Sopenharmony_ci hmdfs_put_lower_path(&lower_path); 24038c2ecf20Sopenharmony_ci if (IS_ERR_OR_NULL(lower_inode)) 24048c2ecf20Sopenharmony_ci return 0; 24058c2ecf20Sopenharmony_ci /* only for directory */ 24068c2ecf20Sopenharmony_ci if (!S_ISDIR(lower_inode->i_mode)) 24078c2ecf20Sopenharmony_ci return 0; 24088c2ecf20Sopenharmony_ci 24098c2ecf20Sopenharmony_ci relative_path = hmdfs_get_dentry_relative_path(dentry); 24108c2ecf20Sopenharmony_ci if (!relative_path) { 24118c2ecf20Sopenharmony_ci hmdfs_err("get dentry relative path failed"); 24128c2ecf20Sopenharmony_ci return 0; 24138c2ecf20Sopenharmony_ci } 24148c2ecf20Sopenharmony_ci mutex_lock(&d_info->remote_cache_list_lock); 24158c2ecf20Sopenharmony_ci list_for_each_entry_safe(item, item_temp, 24168c2ecf20Sopenharmony_ci &(d_info->remote_cache_list_head), list) { 24178c2ecf20Sopenharmony_ci if (item->drop_flag) { 24188c2ecf20Sopenharmony_ci item->drop_flag = 0; 24198c2ecf20Sopenharmony_ci continue; 24208c2ecf20Sopenharmony_ci } 24218c2ecf20Sopenharmony_ci mutex_unlock(&d_info->remote_cache_list_lock); 24228c2ecf20Sopenharmony_ci hmdfs_send_drop_push(item->con, relative_path); 24238c2ecf20Sopenharmony_ci mutex_lock(&d_info->remote_cache_list_lock); 24248c2ecf20Sopenharmony_ci list_del(&item->list); 24258c2ecf20Sopenharmony_ci kfree(item); 24268c2ecf20Sopenharmony_ci } 24278c2ecf20Sopenharmony_ci mutex_unlock(&d_info->remote_cache_list_lock); 24288c2ecf20Sopenharmony_ci 24298c2ecf20Sopenharmony_ci kfree(relative_path); 24308c2ecf20Sopenharmony_ci return 0; 24318c2ecf20Sopenharmony_ci} 24328c2ecf20Sopenharmony_ci 24338c2ecf20Sopenharmony_ci/* Clear the dentry cache files of target directory */ 24348c2ecf20Sopenharmony_ciint hmdfs_clear_cache_dents(struct dentry *dentry, bool remove_cache) 24358c2ecf20Sopenharmony_ci{ 24368c2ecf20Sopenharmony_ci struct clearcache_item *item = NULL; 24378c2ecf20Sopenharmony_ci struct clearcache_item *item_temp = NULL; 24388c2ecf20Sopenharmony_ci struct hmdfs_dentry_info *d_info = hmdfs_d(dentry); 24398c2ecf20Sopenharmony_ci char *path = NULL; 24408c2ecf20Sopenharmony_ci 24418c2ecf20Sopenharmony_ci if (!d_info) 24428c2ecf20Sopenharmony_ci return 0; 24438c2ecf20Sopenharmony_ci 24448c2ecf20Sopenharmony_ci spin_lock(&d_info->cache_list_lock); 24458c2ecf20Sopenharmony_ci list_for_each_entry_safe(item, item_temp, &(d_info->cache_list_head), 24468c2ecf20Sopenharmony_ci list) { 24478c2ecf20Sopenharmony_ci list_del_init(&item->list); 24488c2ecf20Sopenharmony_ci kref_put(&item->ref, release_cache_item); 24498c2ecf20Sopenharmony_ci } 24508c2ecf20Sopenharmony_ci spin_unlock(&d_info->cache_list_lock); 24518c2ecf20Sopenharmony_ci 24528c2ecf20Sopenharmony_ci if (!remove_cache) 24538c2ecf20Sopenharmony_ci return 0; 24548c2ecf20Sopenharmony_ci 24558c2ecf20Sopenharmony_ci /* it also need confirm that there are no dentryfile_dev* 24568c2ecf20Sopenharmony_ci * under this dentry 24578c2ecf20Sopenharmony_ci */ 24588c2ecf20Sopenharmony_ci path = hmdfs_get_dentry_relative_path(dentry); 24598c2ecf20Sopenharmony_ci 24608c2ecf20Sopenharmony_ci if (unlikely(!path)) { 24618c2ecf20Sopenharmony_ci hmdfs_err("get relative path failed"); 24628c2ecf20Sopenharmony_ci return 0; 24638c2ecf20Sopenharmony_ci } 24648c2ecf20Sopenharmony_ci 24658c2ecf20Sopenharmony_ci cache_file_destroy_by_path(hmdfs_sb(dentry->d_sb), path); 24668c2ecf20Sopenharmony_ci 24678c2ecf20Sopenharmony_ci kfree(path); 24688c2ecf20Sopenharmony_ci return 0; 24698c2ecf20Sopenharmony_ci} 24708c2ecf20Sopenharmony_ci 24718c2ecf20Sopenharmony_civoid hmdfs_mark_drop_flag(uint64_t device_id, struct dentry *dentry) 24728c2ecf20Sopenharmony_ci{ 24738c2ecf20Sopenharmony_ci struct remotecache_item *item = NULL; 24748c2ecf20Sopenharmony_ci struct hmdfs_dentry_info *d_info = NULL; 24758c2ecf20Sopenharmony_ci 24768c2ecf20Sopenharmony_ci d_info = hmdfs_d(dentry); 24778c2ecf20Sopenharmony_ci if (!d_info) { 24788c2ecf20Sopenharmony_ci hmdfs_err("d_info null and return"); 24798c2ecf20Sopenharmony_ci return; 24808c2ecf20Sopenharmony_ci } 24818c2ecf20Sopenharmony_ci 24828c2ecf20Sopenharmony_ci mutex_lock(&d_info->remote_cache_list_lock); 24838c2ecf20Sopenharmony_ci list_for_each_entry(item, &(d_info->remote_cache_list_head), list) { 24848c2ecf20Sopenharmony_ci if (item->con->device_id == device_id) { 24858c2ecf20Sopenharmony_ci item->drop_flag = 1; 24868c2ecf20Sopenharmony_ci break; 24878c2ecf20Sopenharmony_ci } 24888c2ecf20Sopenharmony_ci } 24898c2ecf20Sopenharmony_ci mutex_unlock(&d_info->remote_cache_list_lock); 24908c2ecf20Sopenharmony_ci} 24918c2ecf20Sopenharmony_ci 24928c2ecf20Sopenharmony_civoid hmdfs_clear_drop_flag(struct dentry *dentry) 24938c2ecf20Sopenharmony_ci{ 24948c2ecf20Sopenharmony_ci struct remotecache_item *item = NULL; 24958c2ecf20Sopenharmony_ci struct hmdfs_dentry_info *d_info = NULL; 24968c2ecf20Sopenharmony_ci 24978c2ecf20Sopenharmony_ci if (!dentry) { 24988c2ecf20Sopenharmony_ci hmdfs_err("dentry null and return"); 24998c2ecf20Sopenharmony_ci return; 25008c2ecf20Sopenharmony_ci } 25018c2ecf20Sopenharmony_ci 25028c2ecf20Sopenharmony_ci d_info = hmdfs_d(dentry); 25038c2ecf20Sopenharmony_ci if (!d_info) { 25048c2ecf20Sopenharmony_ci hmdfs_err("d_info null and return"); 25058c2ecf20Sopenharmony_ci return; 25068c2ecf20Sopenharmony_ci } 25078c2ecf20Sopenharmony_ci 25088c2ecf20Sopenharmony_ci mutex_lock(&d_info->remote_cache_list_lock); 25098c2ecf20Sopenharmony_ci list_for_each_entry(item, &(d_info->remote_cache_list_head), list) { 25108c2ecf20Sopenharmony_ci if (item->drop_flag) 25118c2ecf20Sopenharmony_ci item->drop_flag = 0; 25128c2ecf20Sopenharmony_ci } 25138c2ecf20Sopenharmony_ci mutex_unlock(&d_info->remote_cache_list_lock); 25148c2ecf20Sopenharmony_ci} 25158c2ecf20Sopenharmony_ci 25168c2ecf20Sopenharmony_ci#define DUSTBIN_SUFFIX ".hwbk" 25178c2ecf20Sopenharmony_cistatic void hmdfs_rename_bak(struct dentry *dentry) 25188c2ecf20Sopenharmony_ci{ 25198c2ecf20Sopenharmony_ci struct path lower_path; 25208c2ecf20Sopenharmony_ci struct dentry *lower_parent = NULL; 25218c2ecf20Sopenharmony_ci struct dentry *lower_dentry = NULL; 25228c2ecf20Sopenharmony_ci struct dentry *new_dentry = NULL; 25238c2ecf20Sopenharmony_ci char *name = NULL; 25248c2ecf20Sopenharmony_ci int len = 0; 25258c2ecf20Sopenharmony_ci int err = 0; 25268c2ecf20Sopenharmony_ci 25278c2ecf20Sopenharmony_ci hmdfs_get_lower_path(dentry, &lower_path); 25288c2ecf20Sopenharmony_ci lower_dentry = lower_path.dentry; 25298c2ecf20Sopenharmony_ci len = strlen(lower_dentry->d_name.name) + strlen(DUSTBIN_SUFFIX) + 2; 25308c2ecf20Sopenharmony_ci if (len >= NAME_MAX) { 25318c2ecf20Sopenharmony_ci err = -ENAMETOOLONG; 25328c2ecf20Sopenharmony_ci goto put_lower_path; 25338c2ecf20Sopenharmony_ci } 25348c2ecf20Sopenharmony_ci 25358c2ecf20Sopenharmony_ci name = kmalloc(len, GFP_KERNEL); 25368c2ecf20Sopenharmony_ci if (!name) { 25378c2ecf20Sopenharmony_ci err = -ENOMEM; 25388c2ecf20Sopenharmony_ci goto put_lower_path; 25398c2ecf20Sopenharmony_ci } 25408c2ecf20Sopenharmony_ci 25418c2ecf20Sopenharmony_ci snprintf(name, len, ".%s%s", lower_dentry->d_name.name, DUSTBIN_SUFFIX); 25428c2ecf20Sopenharmony_ci err = mnt_want_write(lower_path.mnt); 25438c2ecf20Sopenharmony_ci if (err) { 25448c2ecf20Sopenharmony_ci hmdfs_info("get write access failed, err %d", err); 25458c2ecf20Sopenharmony_ci goto free_name; 25468c2ecf20Sopenharmony_ci } 25478c2ecf20Sopenharmony_ci 25488c2ecf20Sopenharmony_ci lower_parent = lock_parent(lower_dentry); 25498c2ecf20Sopenharmony_ci new_dentry = lookup_one_len(name, lower_parent, strlen(name)); 25508c2ecf20Sopenharmony_ci if (IS_ERR(new_dentry)) { 25518c2ecf20Sopenharmony_ci err = PTR_ERR(new_dentry); 25528c2ecf20Sopenharmony_ci hmdfs_info("lookup new dentry failed, err %d", err); 25538c2ecf20Sopenharmony_ci goto unlock_parent; 25548c2ecf20Sopenharmony_ci } 25558c2ecf20Sopenharmony_ci 25568c2ecf20Sopenharmony_ci err = vfs_rename(d_inode(lower_parent), lower_dentry, 25578c2ecf20Sopenharmony_ci d_inode(lower_parent), new_dentry, NULL, 0); 25588c2ecf20Sopenharmony_ci 25598c2ecf20Sopenharmony_ci dput(new_dentry); 25608c2ecf20Sopenharmony_ciunlock_parent: 25618c2ecf20Sopenharmony_ci unlock_dir(lower_parent); 25628c2ecf20Sopenharmony_ci mnt_drop_write(lower_path.mnt); 25638c2ecf20Sopenharmony_cifree_name: 25648c2ecf20Sopenharmony_ci kfree(name); 25658c2ecf20Sopenharmony_ciput_lower_path: 25668c2ecf20Sopenharmony_ci hmdfs_put_lower_path(&lower_path); 25678c2ecf20Sopenharmony_ci 25688c2ecf20Sopenharmony_ci if (err) 25698c2ecf20Sopenharmony_ci hmdfs_err("failed to rename file, err %d", err); 25708c2ecf20Sopenharmony_ci} 25718c2ecf20Sopenharmony_ci 25728c2ecf20Sopenharmony_ciint hmdfs_root_unlink(uint64_t device_id, struct path *root_path, 25738c2ecf20Sopenharmony_ci const char *unlink_dir, const char *unlink_name) 25748c2ecf20Sopenharmony_ci{ 25758c2ecf20Sopenharmony_ci int err = 0; 25768c2ecf20Sopenharmony_ci struct path path; 25778c2ecf20Sopenharmony_ci struct dentry *child_dentry = NULL; 25788c2ecf20Sopenharmony_ci struct inode *dir = NULL; 25798c2ecf20Sopenharmony_ci struct inode *child_inode = NULL; 25808c2ecf20Sopenharmony_ci kuid_t tmp_uid; 25818c2ecf20Sopenharmony_ci 25828c2ecf20Sopenharmony_ci err = vfs_path_lookup(root_path->dentry, root_path->mnt, 25838c2ecf20Sopenharmony_ci unlink_dir, LOOKUP_DIRECTORY, &path); 25848c2ecf20Sopenharmony_ci if (err) { 25858c2ecf20Sopenharmony_ci hmdfs_err("found path failed err = %d", err); 25868c2ecf20Sopenharmony_ci return err; 25878c2ecf20Sopenharmony_ci } 25888c2ecf20Sopenharmony_ci dir = d_inode(path.dentry); 25898c2ecf20Sopenharmony_ci inode_lock_nested(dir, I_MUTEX_PARENT); 25908c2ecf20Sopenharmony_ci 25918c2ecf20Sopenharmony_ci child_dentry = lookup_one_len(unlink_name, path.dentry, 25928c2ecf20Sopenharmony_ci strlen(unlink_name)); 25938c2ecf20Sopenharmony_ci if (IS_ERR(child_dentry)) { 25948c2ecf20Sopenharmony_ci err = PTR_ERR(child_dentry); 25958c2ecf20Sopenharmony_ci hmdfs_err("lookup_one_len failed, err = %d", err); 25968c2ecf20Sopenharmony_ci goto unlock_out; 25978c2ecf20Sopenharmony_ci } 25988c2ecf20Sopenharmony_ci if (d_is_negative(child_dentry)) { 25998c2ecf20Sopenharmony_ci err = -ENOENT; 26008c2ecf20Sopenharmony_ci dput(child_dentry); 26018c2ecf20Sopenharmony_ci goto unlock_out; 26028c2ecf20Sopenharmony_ci } 26038c2ecf20Sopenharmony_ci child_inode = d_inode(child_dentry); 26048c2ecf20Sopenharmony_ci if (!child_inode) 26058c2ecf20Sopenharmony_ci goto unlock_out; 26068c2ecf20Sopenharmony_ci 26078c2ecf20Sopenharmony_ci tmp_uid = hmdfs_override_inode_uid(dir); 26088c2ecf20Sopenharmony_ci 26098c2ecf20Sopenharmony_ci hmdfs_mark_drop_flag(device_id, path.dentry); 26108c2ecf20Sopenharmony_ci ihold(child_inode); 26118c2ecf20Sopenharmony_ci err = vfs_unlink(dir, child_dentry, NULL); 26128c2ecf20Sopenharmony_ci /* 26138c2ecf20Sopenharmony_ci * -EOWNERDEAD means we want to put the file in a specail dir instead of 26148c2ecf20Sopenharmony_ci * deleting it, specifically dustbin in phone, so that user can 26158c2ecf20Sopenharmony_ci * recover the deleted images and videos. 26168c2ecf20Sopenharmony_ci */ 26178c2ecf20Sopenharmony_ci if (err == -EOWNERDEAD) { 26188c2ecf20Sopenharmony_ci hmdfs_rename_bak(child_dentry); 26198c2ecf20Sopenharmony_ci err = 0; 26208c2ecf20Sopenharmony_ci } 26218c2ecf20Sopenharmony_ci if (err) 26228c2ecf20Sopenharmony_ci hmdfs_err("unlink path failed err = %d", err); 26238c2ecf20Sopenharmony_ci hmdfs_revert_inode_uid(dir, tmp_uid); 26248c2ecf20Sopenharmony_ci dput(child_dentry); 26258c2ecf20Sopenharmony_ci 26268c2ecf20Sopenharmony_ciunlock_out: 26278c2ecf20Sopenharmony_ci inode_unlock(dir); 26288c2ecf20Sopenharmony_ci if (child_inode) 26298c2ecf20Sopenharmony_ci iput(child_inode); 26308c2ecf20Sopenharmony_ci path_put(&path); 26318c2ecf20Sopenharmony_ci return err; 26328c2ecf20Sopenharmony_ci} 26338c2ecf20Sopenharmony_ci 26348c2ecf20Sopenharmony_cistruct dentry *hmdfs_root_mkdir(uint64_t device_id, const char *local_dst_path, 26358c2ecf20Sopenharmony_ci const char *mkdir_dir, const char *mkdir_name, 26368c2ecf20Sopenharmony_ci umode_t mode) 26378c2ecf20Sopenharmony_ci{ 26388c2ecf20Sopenharmony_ci int err; 26398c2ecf20Sopenharmony_ci struct path path; 26408c2ecf20Sopenharmony_ci struct dentry *child_dentry = NULL; 26418c2ecf20Sopenharmony_ci struct dentry *ret = NULL; 26428c2ecf20Sopenharmony_ci char *mkdir_path = NULL; 26438c2ecf20Sopenharmony_ci char *mkdir_abs_path = NULL; 26448c2ecf20Sopenharmony_ci 26458c2ecf20Sopenharmony_ci mkdir_path = hmdfs_connect_path(mkdir_dir, mkdir_name); 26468c2ecf20Sopenharmony_ci if (!mkdir_path) 26478c2ecf20Sopenharmony_ci return ERR_PTR(-EACCES); 26488c2ecf20Sopenharmony_ci 26498c2ecf20Sopenharmony_ci mkdir_abs_path = 26508c2ecf20Sopenharmony_ci hmdfs_get_dentry_absolute_path(local_dst_path, mkdir_path); 26518c2ecf20Sopenharmony_ci if (!mkdir_abs_path) { 26528c2ecf20Sopenharmony_ci ret = ERR_PTR(-ENOMEM); 26538c2ecf20Sopenharmony_ci goto out; 26548c2ecf20Sopenharmony_ci } 26558c2ecf20Sopenharmony_ci 26568c2ecf20Sopenharmony_ci child_dentry = kern_path_create(AT_FDCWD, mkdir_abs_path, 26578c2ecf20Sopenharmony_ci &path, LOOKUP_DIRECTORY); 26588c2ecf20Sopenharmony_ci if (IS_ERR(child_dentry)) { 26598c2ecf20Sopenharmony_ci ret = child_dentry; 26608c2ecf20Sopenharmony_ci goto out; 26618c2ecf20Sopenharmony_ci } 26628c2ecf20Sopenharmony_ci 26638c2ecf20Sopenharmony_ci hmdfs_mark_drop_flag(device_id, child_dentry->d_parent); 26648c2ecf20Sopenharmony_ci err = vfs_mkdir(d_inode(path.dentry), child_dentry, mode); 26658c2ecf20Sopenharmony_ci if (err) { 26668c2ecf20Sopenharmony_ci hmdfs_err("mkdir failed! err=%d", err); 26678c2ecf20Sopenharmony_ci ret = ERR_PTR(err); 26688c2ecf20Sopenharmony_ci goto out_put; 26698c2ecf20Sopenharmony_ci } 26708c2ecf20Sopenharmony_ci ret = dget(child_dentry); 26718c2ecf20Sopenharmony_ciout_put: 26728c2ecf20Sopenharmony_ci done_path_create(&path, child_dentry); 26738c2ecf20Sopenharmony_ciout: 26748c2ecf20Sopenharmony_ci kfree(mkdir_path); 26758c2ecf20Sopenharmony_ci kfree(mkdir_abs_path); 26768c2ecf20Sopenharmony_ci return ret; 26778c2ecf20Sopenharmony_ci} 26788c2ecf20Sopenharmony_ci 26798c2ecf20Sopenharmony_cistruct dentry *hmdfs_root_create(uint64_t device_id, const char *local_dst_path, 26808c2ecf20Sopenharmony_ci const char *create_dir, 26818c2ecf20Sopenharmony_ci const char *create_name, 26828c2ecf20Sopenharmony_ci umode_t mode, bool want_excl) 26838c2ecf20Sopenharmony_ci{ 26848c2ecf20Sopenharmony_ci int err; 26858c2ecf20Sopenharmony_ci struct path path; 26868c2ecf20Sopenharmony_ci struct dentry *child_dentry = NULL; 26878c2ecf20Sopenharmony_ci struct dentry *ret = NULL; 26888c2ecf20Sopenharmony_ci char *create_path = NULL; 26898c2ecf20Sopenharmony_ci char *create_abs_path = NULL; 26908c2ecf20Sopenharmony_ci 26918c2ecf20Sopenharmony_ci create_path = hmdfs_connect_path(create_dir, create_name); 26928c2ecf20Sopenharmony_ci if (!create_path) 26938c2ecf20Sopenharmony_ci return ERR_PTR(-EACCES); 26948c2ecf20Sopenharmony_ci 26958c2ecf20Sopenharmony_ci create_abs_path = 26968c2ecf20Sopenharmony_ci hmdfs_get_dentry_absolute_path(local_dst_path, create_path); 26978c2ecf20Sopenharmony_ci if (!create_abs_path) { 26988c2ecf20Sopenharmony_ci ret = ERR_PTR(-ENOMEM); 26998c2ecf20Sopenharmony_ci goto out; 27008c2ecf20Sopenharmony_ci } 27018c2ecf20Sopenharmony_ci 27028c2ecf20Sopenharmony_ci child_dentry = kern_path_create(AT_FDCWD, create_abs_path, &path, 0); 27038c2ecf20Sopenharmony_ci 27048c2ecf20Sopenharmony_ci if (IS_ERR(child_dentry)) { 27058c2ecf20Sopenharmony_ci ret = child_dentry; 27068c2ecf20Sopenharmony_ci goto out; 27078c2ecf20Sopenharmony_ci } 27088c2ecf20Sopenharmony_ci hmdfs_mark_drop_flag(device_id, child_dentry->d_parent); 27098c2ecf20Sopenharmony_ci err = vfs_create(d_inode(path.dentry), child_dentry, mode, want_excl); 27108c2ecf20Sopenharmony_ci if (err) { 27118c2ecf20Sopenharmony_ci hmdfs_err("path create failed! err=%d", err); 27128c2ecf20Sopenharmony_ci ret = ERR_PTR(err); 27138c2ecf20Sopenharmony_ci goto out_put; 27148c2ecf20Sopenharmony_ci } 27158c2ecf20Sopenharmony_ci ret = dget(child_dentry); 27168c2ecf20Sopenharmony_ciout_put: 27178c2ecf20Sopenharmony_ci done_path_create(&path, child_dentry); 27188c2ecf20Sopenharmony_ciout: 27198c2ecf20Sopenharmony_ci kfree(create_path); 27208c2ecf20Sopenharmony_ci kfree(create_abs_path); 27218c2ecf20Sopenharmony_ci return ret; 27228c2ecf20Sopenharmony_ci} 27238c2ecf20Sopenharmony_ci 27248c2ecf20Sopenharmony_ciint hmdfs_root_rmdir(uint64_t device_id, struct path *root_path, 27258c2ecf20Sopenharmony_ci const char *rmdir_dir, const char *rmdir_name) 27268c2ecf20Sopenharmony_ci{ 27278c2ecf20Sopenharmony_ci int err = 0; 27288c2ecf20Sopenharmony_ci struct path path; 27298c2ecf20Sopenharmony_ci struct dentry *child_dentry = NULL; 27308c2ecf20Sopenharmony_ci struct inode *dir = NULL; 27318c2ecf20Sopenharmony_ci 27328c2ecf20Sopenharmony_ci err = vfs_path_lookup(root_path->dentry, root_path->mnt, 27338c2ecf20Sopenharmony_ci rmdir_dir, LOOKUP_DIRECTORY, &path); 27348c2ecf20Sopenharmony_ci if (err) { 27358c2ecf20Sopenharmony_ci hmdfs_err("found path failed err = %d", err); 27368c2ecf20Sopenharmony_ci return err; 27378c2ecf20Sopenharmony_ci } 27388c2ecf20Sopenharmony_ci dir = d_inode(path.dentry); 27398c2ecf20Sopenharmony_ci inode_lock_nested(dir, I_MUTEX_PARENT); 27408c2ecf20Sopenharmony_ci 27418c2ecf20Sopenharmony_ci child_dentry = lookup_one_len(rmdir_name, path.dentry, 27428c2ecf20Sopenharmony_ci strlen(rmdir_name)); 27438c2ecf20Sopenharmony_ci if (IS_ERR(child_dentry)) { 27448c2ecf20Sopenharmony_ci err = PTR_ERR(child_dentry); 27458c2ecf20Sopenharmony_ci hmdfs_err("lookup_one_len failed, err = %d", err); 27468c2ecf20Sopenharmony_ci goto unlock_out; 27478c2ecf20Sopenharmony_ci } 27488c2ecf20Sopenharmony_ci if (d_is_negative(child_dentry)) { 27498c2ecf20Sopenharmony_ci err = -ENOENT; 27508c2ecf20Sopenharmony_ci dput(child_dentry); 27518c2ecf20Sopenharmony_ci goto unlock_out; 27528c2ecf20Sopenharmony_ci } 27538c2ecf20Sopenharmony_ci 27548c2ecf20Sopenharmony_ci hmdfs_mark_drop_flag(device_id, path.dentry); 27558c2ecf20Sopenharmony_ci err = vfs_rmdir(dir, child_dentry); 27568c2ecf20Sopenharmony_ci if (err) 27578c2ecf20Sopenharmony_ci hmdfs_err("rmdir failed err = %d", err); 27588c2ecf20Sopenharmony_ci dput(child_dentry); 27598c2ecf20Sopenharmony_ci 27608c2ecf20Sopenharmony_ciunlock_out: 27618c2ecf20Sopenharmony_ci inode_unlock(dir); 27628c2ecf20Sopenharmony_ci path_put(&path); 27638c2ecf20Sopenharmony_ci return err; 27648c2ecf20Sopenharmony_ci} 27658c2ecf20Sopenharmony_ci 27668c2ecf20Sopenharmony_ciint hmdfs_root_rename(struct hmdfs_sb_info *sbi, uint64_t device_id, 27678c2ecf20Sopenharmony_ci const char *oldpath, const char *oldname, 27688c2ecf20Sopenharmony_ci const char *newpath, const char *newname, 27698c2ecf20Sopenharmony_ci unsigned int flags) 27708c2ecf20Sopenharmony_ci{ 27718c2ecf20Sopenharmony_ci int err = 0; 27728c2ecf20Sopenharmony_ci struct path path_dst; 27738c2ecf20Sopenharmony_ci struct path path_old; 27748c2ecf20Sopenharmony_ci struct path path_new; 27758c2ecf20Sopenharmony_ci struct dentry *trap = NULL; 27768c2ecf20Sopenharmony_ci struct dentry *old_dentry = NULL; 27778c2ecf20Sopenharmony_ci struct dentry *new_dentry = NULL; 27788c2ecf20Sopenharmony_ci 27798c2ecf20Sopenharmony_ci err = kern_path(sbi->local_dst, 0, &path_dst); 27808c2ecf20Sopenharmony_ci if (err) { 27818c2ecf20Sopenharmony_ci hmdfs_err("kern_path for local dst failed %d", err); 27828c2ecf20Sopenharmony_ci return err; 27838c2ecf20Sopenharmony_ci } 27848c2ecf20Sopenharmony_ci 27858c2ecf20Sopenharmony_ci err = vfs_path_lookup(path_dst.dentry, path_dst.mnt, oldpath, 0, 27868c2ecf20Sopenharmony_ci &path_old); 27878c2ecf20Sopenharmony_ci if (err) { 27888c2ecf20Sopenharmony_ci hmdfs_info("lookup oldpath from local_dst failed, err %d", err); 27898c2ecf20Sopenharmony_ci goto put_path_dst; 27908c2ecf20Sopenharmony_ci } 27918c2ecf20Sopenharmony_ci 27928c2ecf20Sopenharmony_ci err = vfs_path_lookup(path_dst.dentry, path_dst.mnt, newpath, 0, 27938c2ecf20Sopenharmony_ci &path_new); 27948c2ecf20Sopenharmony_ci if (err) { 27958c2ecf20Sopenharmony_ci hmdfs_info("lookup newpath from local_dst failed, err %d", err); 27968c2ecf20Sopenharmony_ci goto put_path_old; 27978c2ecf20Sopenharmony_ci } 27988c2ecf20Sopenharmony_ci 27998c2ecf20Sopenharmony_ci err = mnt_want_write(path_dst.mnt); 28008c2ecf20Sopenharmony_ci if (err) { 28018c2ecf20Sopenharmony_ci hmdfs_info("get write access failed for local_dst, err %d", 28028c2ecf20Sopenharmony_ci err); 28038c2ecf20Sopenharmony_ci goto put_path_new; 28048c2ecf20Sopenharmony_ci } 28058c2ecf20Sopenharmony_ci 28068c2ecf20Sopenharmony_ci trap = lock_rename(path_new.dentry, path_old.dentry); 28078c2ecf20Sopenharmony_ci 28088c2ecf20Sopenharmony_ci old_dentry = lookup_one_len(oldname, path_old.dentry, strlen(oldname)); 28098c2ecf20Sopenharmony_ci if (IS_ERR(old_dentry)) { 28108c2ecf20Sopenharmony_ci err = PTR_ERR(old_dentry); 28118c2ecf20Sopenharmony_ci hmdfs_info("lookup old dentry failed, err %d", err); 28128c2ecf20Sopenharmony_ci goto unlock; 28138c2ecf20Sopenharmony_ci } 28148c2ecf20Sopenharmony_ci 28158c2ecf20Sopenharmony_ci /* source should not be ancestor of target */ 28168c2ecf20Sopenharmony_ci if (old_dentry == trap) { 28178c2ecf20Sopenharmony_ci err = -EINVAL; 28188c2ecf20Sopenharmony_ci goto put_old_dentry; 28198c2ecf20Sopenharmony_ci } 28208c2ecf20Sopenharmony_ci 28218c2ecf20Sopenharmony_ci new_dentry = lookup_one_len(newname, path_new.dentry, strlen(newname)); 28228c2ecf20Sopenharmony_ci if (IS_ERR(new_dentry)) { 28238c2ecf20Sopenharmony_ci err = PTR_ERR(new_dentry); 28248c2ecf20Sopenharmony_ci hmdfs_info("lookup new dentry failed, err %d", err); 28258c2ecf20Sopenharmony_ci goto put_old_dentry; 28268c2ecf20Sopenharmony_ci } 28278c2ecf20Sopenharmony_ci 28288c2ecf20Sopenharmony_ci /* 28298c2ecf20Sopenharmony_ci * Exchange rename is not supported, thus target should not be an 28308c2ecf20Sopenharmony_ci * ancestor of source. 28318c2ecf20Sopenharmony_ci */ 28328c2ecf20Sopenharmony_ci if (trap == new_dentry) { 28338c2ecf20Sopenharmony_ci err = -ENOTEMPTY; 28348c2ecf20Sopenharmony_ci goto put_new_dentry; 28358c2ecf20Sopenharmony_ci } 28368c2ecf20Sopenharmony_ci 28378c2ecf20Sopenharmony_ci if (d_is_positive(new_dentry) && (flags & RENAME_NOREPLACE)) { 28388c2ecf20Sopenharmony_ci err = -EEXIST; 28398c2ecf20Sopenharmony_ci goto put_new_dentry; 28408c2ecf20Sopenharmony_ci } 28418c2ecf20Sopenharmony_ci 28428c2ecf20Sopenharmony_ci hmdfs_mark_drop_flag(device_id, path_old.dentry); 28438c2ecf20Sopenharmony_ci if (path_old.dentry != path_new.dentry) 28448c2ecf20Sopenharmony_ci hmdfs_mark_drop_flag(device_id, path_new.dentry); 28458c2ecf20Sopenharmony_ci 28468c2ecf20Sopenharmony_ci err = vfs_rename(d_inode(path_old.dentry), old_dentry, 28478c2ecf20Sopenharmony_ci d_inode(path_new.dentry), new_dentry, NULL, 0); 28488c2ecf20Sopenharmony_ci 28498c2ecf20Sopenharmony_ciput_new_dentry: 28508c2ecf20Sopenharmony_ci dput(new_dentry); 28518c2ecf20Sopenharmony_ciput_old_dentry: 28528c2ecf20Sopenharmony_ci dput(old_dentry); 28538c2ecf20Sopenharmony_ciunlock: 28548c2ecf20Sopenharmony_ci unlock_rename(path_new.dentry, path_old.dentry); 28558c2ecf20Sopenharmony_ci mnt_drop_write(path_dst.mnt); 28568c2ecf20Sopenharmony_ciput_path_new: 28578c2ecf20Sopenharmony_ci path_put(&path_new); 28588c2ecf20Sopenharmony_ciput_path_old: 28598c2ecf20Sopenharmony_ci path_put(&path_old); 28608c2ecf20Sopenharmony_ciput_path_dst: 28618c2ecf20Sopenharmony_ci path_put(&path_dst); 28628c2ecf20Sopenharmony_ci 28638c2ecf20Sopenharmony_ci return err; 28648c2ecf20Sopenharmony_ci} 28658c2ecf20Sopenharmony_ci 28668c2ecf20Sopenharmony_ciint hmdfs_get_path_in_sb(struct super_block *sb, const char *name, 28678c2ecf20Sopenharmony_ci unsigned int flags, struct path *path) 28688c2ecf20Sopenharmony_ci{ 28698c2ecf20Sopenharmony_ci int err; 28708c2ecf20Sopenharmony_ci 28718c2ecf20Sopenharmony_ci err = kern_path(name, flags, path); 28728c2ecf20Sopenharmony_ci if (err) { 28738c2ecf20Sopenharmony_ci hmdfs_err("can't get %s %d\n", name, err); 28748c2ecf20Sopenharmony_ci return err; 28758c2ecf20Sopenharmony_ci } 28768c2ecf20Sopenharmony_ci 28778c2ecf20Sopenharmony_ci /* should ensure the path is belong sb */ 28788c2ecf20Sopenharmony_ci if (path->dentry->d_sb != sb) { 28798c2ecf20Sopenharmony_ci err = -EINVAL; 28808c2ecf20Sopenharmony_ci hmdfs_err("Wrong sb: %s on %s", name, 28818c2ecf20Sopenharmony_ci path->dentry->d_sb->s_type->name); 28828c2ecf20Sopenharmony_ci path_put(path); 28838c2ecf20Sopenharmony_ci } 28848c2ecf20Sopenharmony_ci 28858c2ecf20Sopenharmony_ci return err; 28868c2ecf20Sopenharmony_ci} 2887