/* SPDX-License-Identifier: GPL-2.0 */ /* * Copyright (C) 2021. Huawei Technologies Co., Ltd. All rights reserved. * This program is free software; you can redistribute it and/or modify * it under the terms of the GNU General Public License version 2 and * only version 2 as published by the Free Software Foundation. * * This program is distributed in the hope that it will be useful, * but WITHOUT ANY WARRANTY; without even the implied warranty of * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the * GNU General Public License for more details. */ #ifndef EUFS_COMMON_H #define EUFS_COMMON_H #include #include #include #include #include #include #include #include #include #include #include #ifndef EUFS_H #error "Please include euler_common.h by including euler.h" #endif #define EUFS_INODE_CNT_IN_RENAME 4 #define PAGE_DIV_ROUND_UP(x) (((x) + PAGE_SIZE - 1) >> PAGE_SHIFT) #define PAGE_DIV_ROUND_DOWN(x) (((x)) >> PAGE_SHIFT) #define clear_opt(o, opt) (o &= ~EUFS_MOUNT_##opt) #define set_opt(o, opt) (o |= EUFS_MOUNT_##opt) #define test_opt(sb, opt) (EUFS_SB(sb)->s_mount_opt & EUFS_MOUNT_##opt) static __always_inline void *o2p(struct super_block *sb, u64 offset); static __always_inline u64 p2o(struct super_block *sb, void *ptr); static __always_inline struct eufs_sb_info *EUFS_SB(struct super_block *sb) { return sb->s_fs_info; } static __always_inline struct eufs_inode_info *EUFS_I(struct inode *inode) { return container_of(inode, struct eufs_inode_info, vfs_inode); } static __always_inline struct eufs_inode *EUFS_PI(struct inode *inode) { return (struct eufs_inode *)o2p(inode->i_sb, inode->i_ino); } static __always_inline unsigned long eufs_pi2ino(struct super_block *sb, struct eufs_inode *pi) { return p2o(sb, EUFS_HEAD_PI(pi)); } static __always_inline struct eufs_super_block * eufs_get_super(struct super_block *sb) { struct eufs_sb_info *sbi = EUFS_SB(sb); return (struct eufs_super_block *)sbi->virt_addr; } static __always_inline void *eufs_get_renamej(struct super_block *sb, int cpu) { struct eufs_sb_info *sbi = EUFS_SB(sb); return (void *)((u64)sbi->renamej + EUFS_RENAMEJ_ENTRY_SIZE * cpu); } /* * o: offset: u64 * p: pointer: void * * s: storage: __le64 */ static __always_inline void *o2p(struct super_block *sb, u64 offset) { if (offset == 0) return NULL; if (offset == -1) return (void *)-1; return (void *)(EUFS_SB(sb)->virt_addr + offset); } static __always_inline u64 p2o(struct super_block *sb, void *ptr) { if (ptr == NULL) return 0; if (ptr == (void *)-1) return -1; return (u64)(ptr - EUFS_SB(sb)->virt_addr); } /* pointer to storage */ static __always_inline __le64 p2s(struct super_block *sb, void *ptr) { return cpu_to_le64(p2o(sb, ptr)); } /* storage to pointer */ static __always_inline void *s2p(struct super_block *sb, __le64 s) { return o2p(sb, le64_to_cpu(s)); } static __always_inline bool eufs_access_ok(struct super_block *sb, const void *pointer, unsigned long sz) { return true; } #define eufs_ptr_fast_check_b(ptr) 0 #define eufs_ptr_fast_check(ptr) BUG_ON(eufs_ptr_fast_check_b(ptr)) #define HASHLEN_LEN(hashlen) (((hashlen) >> 48) & 0xff) static __always_inline hashlen_t hash(const char *name, size_t len) { static const int seed = 131; u64 r = 0; int i; for (i = 0; i < len; ++i) r = r * seed + (int)name[i]; return (u64)len << 48 | (r & 0xffffffffffff); } static __always_inline bool key_equals(struct super_block *sb, const char *key, hashlen_t hashlen, const struct nv_dict_entry *de) { int len; struct nv_name_ext *p; NV_ASSERT(key); NV_ASSERT(hashlen); if (hashlen != de->hv) return false; len = HASHLEN_LEN(hashlen); if (likely(len <= FIRST_LEN)) return memcmp(de->name, key, len) == 0; if (memcmp(de->name, key, FIRST_LEN)) return false; eufs_dbg("first len ok\n"); len -= FIRST_LEN; p = s2p(sb, de->nextname); key += FIRST_LEN; while (len > FOLLOW_LEN) { eufs_dbg("check again p:%*s key:%*s\n", (int)FOLLOW_LEN, p->name, (int)FOLLOW_LEN, key); if (memcmp(p->name, key, FOLLOW_LEN)) return false; p = s2p(sb, p->nextname); key += FOLLOW_LEN; len -= FOLLOW_LEN; } eufs_dbg("final check name p:%*s key:%*s\n", len, p->name, len, key); return !memcmp(p->name, key, len); } static __always_inline void eufs_flush_pi(struct eufs_inode *pi) { eufs_flush_cacheline(pi); eufs_flush_cacheline(&pi->i_fresh); } static __always_inline void inode_dep_lock(struct inode *inode) { mutex_lock(&EUFS_I(inode)->i_dep_lock); } static __always_inline void inode_dep_unlock(struct inode *inode) { mutex_unlock(&EUFS_I(inode)->i_dep_lock); } static __always_inline int inode_is_dep_locked(struct inode *inode) { return mutex_is_locked(&EUFS_I(inode)->i_dep_lock); } static __always_inline void inode_header_lock(struct inode *inode) { mutex_lock(&EUFS_I(inode)->i_header_lock); } static __always_inline void inode_header_unlock(struct inode *inode) { mutex_unlock(&EUFS_I(inode)->i_header_lock); } static __always_inline int inode_is_header_locked(struct inode *inode) { return mutex_is_locked(&EUFS_I(inode)->i_header_lock); } static __always_inline void inode_urgent_lock(struct inode *inode) { mutex_lock(&EUFS_I(inode)->i_urgent_mutex); } static __always_inline void inode_urgent_unlock(struct inode *inode) { mutex_unlock(&EUFS_I(inode)->i_urgent_mutex); } static __always_inline int inode_is_urgent_locked(struct inode *inode) { return mutex_is_locked(&EUFS_I(inode)->i_urgent_mutex); } static __always_inline void inode_leaf_lock(struct inode *inode) { mutex_lock(&EUFS_I(inode)->i_leaf_lock); } static __always_inline void inode_leaf_unlock(struct inode *inode) { mutex_unlock(&EUFS_I(inode)->i_leaf_lock); } #endif /* EUFS_COMMON_H */